首先:不要告诉我使用nodemailer。我正在尝试学习网络编程,并希望从头开始使用多种语言。
我正在尝试做一个相当简单的任务:使用TCP套接字发送SMTP电子邮件。我在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
我现在正在尝试使用Net模块使用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服务器在有机会响应前一个命令之前接收命令一样。这使我相信Python3版本默认提供的Node.js实现中缺少某些内容。
任何线索或其他想法将不胜感激。
我希望我的Node.js实现与Python3实现一样工作。
答案 0 :(得分:0)
socket.write
是异步函数。您不能仅列出socket.write
的列表并期望它们按顺序运行。
您必须使用回调并编写类似
的内容socket.write( msg1 , () =>
socket.write( msg2 , () => {
[ .. ]
} );
} );
答案 1 :(得分:0)
将其发布在nodejs / help中并得到答案 (https://github.com/nodejs/help/issues/1741)
可以归结为Python具有阻塞套接字的事实。调用recv()
方法将阻止TCP流,直到服务器返回了某些内容。 Node.js不会这样做,并且它们无法阻止套接字(通过设计)。结果,我需要利用data
事件来继续我的套接字通信。