Как отправить SMTP-сообщение, используя Node.js Net (без Nodemailer) - PullRequest
0 голосов
/ 28 января 2019

Во-первых: не говорите мне использовать nodemailer.Я пытаюсь узнать о сетевом программировании и хочу сделать это с нуля на нескольких языках.

Я пытаюсь выполнить довольно простую задачу: отправить SMTP-сообщение электронной почты с использованием сокетов TCP.У меня есть рабочая реализация в Python 3.6:

from socket import socket, AF_INET, SOCK_STREAM
# Choose a mail server (e.g. Google mail server) and call it mailserver
mailserver = 'gmail-smtp-in.l.google.com'

# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket(AF_INET, SOCK_STREAM)

def recv():
    print(clientSocket.recv(1024).decode())

# Port number may change according to the mail server
clientSocket.connect((mailserver, 25))
recv()

# Send HELO command and print server response.
clientSocket.send('HELO gmail \r\n'.encode())
recv()

# Send MAIL FROM command and print server response.
clientSocket.send('MAIL FROM: <ethan.arrowood@gmail.com>\r\n'.encode())
recv()

# Send RCPT TO command and print server response. 
clientSocket.send('RCPT TO: <ethan.arrowood@gmail.com>\r\n'.encode())
recv()

# Send DATA command and print server response. 
clientSocket.send('DATA\r\n'.encode())
recv()

# Send message data. Make sure to include header lines: From, To, Subject
clientSocket.send('FROM: <ethan.arrowood@gmail.com>\r\n'.encode())
clientSocket.send('TO: <ethan.arrowood@gmail.com>\r\n'.encode())
clientSocket.send('SUBJECT: Testing\r\n'.encode())
clientSocket.send('This is cool!\r\n'.encode())
# Message ends with a single period.
clientSocket.send('.\r\n'.encode())
recv()
# Send QUIT command and get server response
clientSocket.send('QUIT\r\n'.encode())
recv()

. Она работает и выводит в мою консоль следующее:

220 mx.google.com ESMTP m30si710943qtg.40 - gsmtp

250 mx.google.com at your service

250 2.1.0 OK m30si710943qtg.40 - gsmtp

250 2.1.5 OK m30si710943qtg.40 - gsmtp

354  Go ahead m30si710943qtg.40 - gsmtp

250 2.0.0 OK 1548694151 m30si710943qtg.40 - gsmtp

221 2.0.0 closing connection m30si710943qtg.40 - gsmtp

Сейчас я пытаюсь реализовать то же самое с помощью Node.JS 11.7.0 с использованием сетевого модуля.Мой код:

const net = require('net')

const socket = net.createConnection(25, 'gmail-smtp-in.l.google.com', () => {
  console.log('Connected!')

  socket.write('HELO gmail\r\n')

  socket.write('MAIL FROM: <ethan.arrowood@gmail.com>\r\n')

  socket.write('RCPT TO: <ethan.arrowood@gmail.com>\r\n')

  socket.write('DATA\r\n')

  socket.write('FROM: <ethan.arrowood@gmail.com>\r\n')
  socket.write('TO: <ethan.arrowood@gmail.com>\r\n')
  socket.write('SUBJECT: Testing\r\n')
  socket.write('This is cool!\r\n')
  socket.write('.\r\n')

  socket.write('QUIT\r\n')
})

socket.on('data', buff => console.log(buff.toString()))

Этот код не работает и приводит к следующему выводу терминала:

Connected!
220 mx.google.com ESMTP 88si682318qte.245 - gsmtp

250 mx.google.com at your service

451 4.5.0 SMTP protocol violation, see RFC 2821 88si682318qte.245 - gsmtp

Ошибка 451 ничего не говорит.Я не верю, что проблема связана с кодировкой, поскольку Node.js и Python3 по умолчанию используют UTF-8.

Я думаю, что моя ошибка связана с тем, как я звоню .write.Подобно тому, как SMTP-сервер получает команды, прежде чем он получает возможность ответить на предыдущий.Это наводит меня на мысль, что в моей реализации Node.js чего-то не хватает, что предусмотрено по умолчанию в версии Python3.

Любые подсказки или другие идеи будут высоко оценены.

Я ожидаю, что моя реализация Node.js будет работать так же, как реализация Python3.

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Написал это в nodejs / help и получил ответ (https://github.com/nodejs/help/issues/1741)

. Это сводится к тому, что Python имеет блокирующие сокеты. Вызов метода recv() блокировал поток TCP, пока что-то не было возвращенос сервера. Node.js не делает этого, и их невозможно заблокировать сокеты (в зависимости от проекта). В результате мне нужно использовать событие data для продолжения моего взаимодействия с сокетом.

0 голосов
/ 28 января 2019

socket.write - это асинхронная функция.Вы не можете просто составить список socket.write s и ожидать, что они будут выполняться последовательно.

Вы должны использовать обратные вызовы и написать что-то вроде

socket.write( msg1 , () =>
    socket.write( msg2 , () => {
        [ .. ]
    } );
} );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...