如何通过Gmail使用简单的SMTP命令发送电子邮件?

71

为了教育目的,我需要通过SMTP服务器发送电子邮件,使用SMTP的基本和简单规则。

我能够使用smtp4dev完成这个任务。我使用telnet localhost 25,并输入以下命令:

enter image description here

我想使用Gmail SMTP服务器做同样的事情。然而,它需要身份验证和TLS。我无法弄清楚如何在Gmail上进行设置。这是telnet smtp.gmail.com 587的截图:

enter image description here

我搜索并找到了许多链接,包括 维基百科的文章 关于 STARTTLS 命令。但是我无法使用命令行(或在编程语言中自己发送命令)使用 TLS 并对 Gmail 的 SMTP 服务器进行身份验证。有人能帮忙吗?


你可以使用例如Java编写自己的程序来完成这个任务。 - james.garriss
为什么不像使用自己的服务器一样,使用Gmail的25号端口呢? - vbence
这里有一份指南:http://linuxmeerkat.wordpress.com/2013/10/10/emailing-from-a-gmail-acount-via-telnet/ - Pithikos
相关:通过命令行连接到smtp.gmail.com - Piotr Dobrogost
4个回答

120

要通过Gmail发送邮件,您需要使用加密连接。仅使用Telnet是不可能的,但您可以使用类似openssl这样的工具。

要么使用openssl中的starttls选项将纯文本连接转换为加密连接...

openssl s_client -starttls smtp -connect smtp.gmail.com:587 -crlf -ign_eof

或者直接连接到ssl套接字...

openssl s_client -connect smtp.gmail.com:465 -crlf -ign_eof

EHLO localhost

之后,使用Base64编码的用户名/密码对服务器进行身份验证

AUTH PLAIN AG15ZW1haWxAZ21haWwuY29tAG15cGFzc3dvcmQ=

要从命令行获取此内容:

echo -ne '\00user@gmail.com\00password' | base64
AHVzZXJAZ21haWwuY29tAHBhc3N3b3Jk

然后按照你的示例继续使用 "mail from:"

示例会话:

openssl s_client -connect smtp.gmail.com:465 -crlf -ign_eof
[... lots of openssl output ...]
220 mx.google.com ESMTP m46sm11546481eeh.9
EHLO localhost
250-mx.google.com at your service, [1.2.3.4]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH
250 ENHANCEDSTATUSCODES
AUTH PLAIN AG5pY2UudHJ5QGdtYWlsLmNvbQBub2l0c25vdG15cGFzc3dvcmQ=
235 2.7.0 Accepted
MAIL FROM: <gryphius-demo@gmail.com>
250 2.1.0 OK m46sm11546481eeh.9
rcpt to: <somepoorguy@example.com>
250 2.1.5 OK m46sm11546481eeh.9
DATA
354  Go ahead m46sm11546481eeh.9
Subject: it works

yay!
.
250 2.0.0 OK 1339757532 m46sm11546481eeh.9
quit
221 2.0.0 closing connection m46sm11546481eeh.9
read:errno=0

1
抱歉,我不知道在Windows上openssl可执行文件的安装位置在哪里,因为我在这里使用的是Linux。 - Gryphius
@Gryphius 我得到了 OpenSSL 验证返回代码:20(无法获取本地颁发者证书),即客户端身份验证失败,但我仍然能够像上面那样发送电子邮件,请问你能解释一下为什么吗? - codey modey
2
现在 Gmail 要求您使用应用程序密码而不是常规密码来通过 SSL 进行身份验证。请参见:https://security.google.com/settings/security/apppasswords - Pablo Vallejo
3
如果启用“允许较不安全的应用程序访问”,则上述示例仍可运行,网址为:https://www.google.com/settings/security/lesssecureapps。 - Ivan
1
使用GNU的base64从命令行对用户名和密码进行编码:echo -en '\000myemail@gmail.com\000mypassword' | base64(不要转义@)。 - Stefan van den Akker
显示剩余12条评论

28

很遗憾,由于我被迫使用Windows服务器,所以我无法按照上面的答案建议的方式使openssl工作。

但是,我成功地使用了一款名为stunnel的类似程序(可以从这里下载)进行操作。我的灵感来自www.tech-and-dev.com,但我需要稍微修改一下指令。以下是我所做的:

  1. Install telnet client on the windows box.
  2. Download stunnel. (I downloaded and installed a file called stunnel-4.56-installer.exe).
  3. Once installed you then needed to locate the stunnel.conf config file, which in my case I installed to C:\Program Files (x86)\stunnel
  4. Then, you need to open this file in a text viewer such as notepad. Look for [gmail-smtp] and remove the semicolon on the client line below (in the stunnel.conf file, every line that starts with a semicolon is a comment). You should end up with something like:

    [gmail-smtp]
    client = yes
    accept = 127.0.0.1:25
    connect = smtp.gmail.com:465
    

    Once you have done this save the stunnel.conf file and reload the config (to do this use the stunnel GUI program, and click on configuration=>Reload).

现在你应该已经准备好在 Windows Telnet客户端中发送邮件了!
进入 开始=>运行=>cmd

打开 cmd 后,输入以下内容并按 Enter 键:

telnet localhost 25

接下来您应该看到类似以下内容:

220 mx.google.com ESMTP f14sm1400408wbe.2

之后您需要输入以下内容并按回车键进行回复:

helo google

这应该会给您以下回复:

250 mx.google.com at your service

如果您看到这条消息,您需要输入以下内容并按回车键:
ehlo google

这将会给你以下回应:

250-mx.google.com at your service, [212.28.228.49]
250-SIZE 35651584
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH
250 ENHANCEDSTATUSCODES

现在您应该已经准备好使用您的Gmail账户进行身份验证了。请键入以下内容并按回车键:

AUTH LOGIN

这应该会给你以下响应:
334 VXNlcm5hbWU6

这意味着我们可以使用gmail地址和密码进行认证。

然而,由于这是一个加密会话,我们需要用base64编码发送电子邮件和密码。要对您的电子邮件和密码进行编码,您可以使用转换程序或在线网站进行编码(例如base64或在谷歌上搜索“base64在线编码”)。我建议在完成此操作之前不要再次触摸cmd / telnet会话。

例如,test@gmail.com将变成dGVzdEBnbWFpbC5jb20=,密码将变成cGFzc3dvcmQ=

完成后,请复制并粘贴转换后的base64用户名到cmd / telnet会话中,然后按Enter键。 这应该会给您以下响应:

334 UGFzc3dvcmQ6

现在将转换后的base64密码复制并粘贴到cmd/telnet会话中,然后按回车键。如果登录凭据都正确,应该会得到以下响应:
235 2.7.0 Accepted

您现在应按以下格式输入发件人电子邮件地址(应与用户名相同),然后按Enter键:

MAIL FROM:<test@gmail.com>

这应该会给你以下响应:
250 2.1.0 OK x23sm1104292weq.10

现在,您可以以类似的格式输入收件人电子邮件地址并按回车键:
RCPT TO:<recipient@gmail.com>

这将为您提供以下回应:
250 2.1.5 OK x23sm1104292weq.10

现在你需要输入以下内容并按回车键:

DATA

这应该会给你以下的回复:
354  Go ahead x23sm1104292weq.10

现在我们可以开始编写消息了!为此,请按以下格式输入您的消息(提示:请使用记事本进行操作,并将整个消息复制到cmd/telnet会话中):
From: Test <test@gmail.com>
To: Me <recipient@gmail.com>
Subject: Testing email from telnet
This is the body

Adding more lines to the body message.

当你完成邮件后,请输入一个点:

.

这将会给你以下的响应:
250 2.0.0 OK 1288307376 x23sm1104292weq.10

现在您需要通过输入以下内容并按回车键来结束会话:

QUIT

这将会给你以下的响应:
221 2.0.0 closing connection x23sm1104292weq.10
Connection to host lost.

现在您的电子邮件应该已经到达收件人的邮箱啦!


我们能否使用Wireshark捕获通过命令行发送的SMTP数据包?因为我无法这样做。 - POOJA GUPTA

8
没有人提到,我建议使用一个非常好的工具来完成这个目的 - swaks
# yum info swaks
Installed Packages
Name        : swaks
Arch        : noarch
Version     : 20130209.0
Release     : 3.el6
Size        : 287 k
Repo        : installed
From repo   : epel
Summary     : Command-line SMTP transaction tester
URL         : http://www.jetmore.org/john/code/swaks
License     : GPLv2+
Description : Swiss Army Knife SMTP: A command line SMTP tester. Swaks can test
            : various aspects of your SMTP server, including TLS and AUTH.

它有很多选项,几乎可以做你想要的一切。 GMAIL:STARTTLS,SSlv3(是的,在2016年Gmail仍然支持SSlv3)
$ echo "Hello world" | swaks -4 --server smtp.gmail.com:587 --from user@gmail.com --to user@example.net -tls --tls-protocol sslv3 --auth PLAIN --auth-user user@gmail.com --auth-password 7654321 --h-Subject "Test message" --body -
=== Trying smtp.gmail.com:587...
=== Connected to smtp.gmail.com.
<-  220 smtp.gmail.com ESMTP h8sm76342lbd.48 - gsmtp
 -> EHLO www.example.net
<-  250-smtp.gmail.com at your service, [193.243.156.26]
<-  250-SIZE 35882577
<-  250-8BITMIME
<-  250-STARTTLS
<-  250-ENHANCEDSTATUSCODES
<-  250-PIPELINING
<-  250-CHUNKING
<-  250 SMTPUTF8
 -> STARTTLS
<-  220 2.0.0 Ready to start TLS
=== TLS started with cipher SSLv3:RC4-SHA:128
=== TLS no local certificate set
=== TLS peer DN="/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com"
 ~> EHLO www.example.net
<~  250-smtp.gmail.com at your service, [193.243.156.26]
<~  250-SIZE 35882577
<~  250-8BITMIME
<~  250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
<~  250-ENHANCEDSTATUSCODES
<~  250-PIPELINING
<~  250-CHUNKING
<~  250 SMTPUTF8
 ~> AUTH PLAIN AGFhQxsZXguaGhMGdATGV4X2hoYtYWlsLmNvbQBS9TU1MjQ=
<~  235 2.7.0 Accepted
 ~> MAIL FROM:<user@gmail.com>
<~  250 2.1.0 OK h8sm76342lbd.48 - gsmtp
 ~> RCPT TO:<user@example.net>
<~  250 2.1.5 OK h8sm76342lbd.48 - gsmtp
 ~> DATA
<~  354  Go ahead h8sm76342lbd.48 - gsmtp
 ~> Date: Wed, 17 Feb 2016 09:49:03 +0000
 ~> To: user@example.net
 ~> From: user@gmail.com
 ~> Subject: Test message
 ~> X-Mailer: swaks v20130209.0 jetmore.org/john/code/swaks/
 ~>
 ~> Hello world
 ~>
 ~>
 ~> .
<~  250 2.0.0 OK 1455702544 h8sm76342lbd.48 - gsmtp
 ~> QUIT
<~  221 2.0.0 closing connection h8sm76342lbd.48 - gsmtp
=== Connection closed with remote host.

雅虎:TLS又称SMTPS,tlsv1.2。
$ echo "Hello world" | swaks -4 --server smtp.mail.yahoo.com:465 --from user@yahoo.com --to user@gmail.com --tlsc --tls-protocol tlsv1_2 --auth PLAIN --auth-user user@yahoo.com --auth-password 7654321 --h-Subject "Test message" --body -
=== Trying smtp.mail.yahoo.com:465...
=== Connected to smtp.mail.yahoo.com.
=== TLS started with cipher TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128
=== TLS no local certificate set
=== TLS peer DN="/C=US/ST=California/L=Sunnyvale/O=Yahoo Inc./OU=Information Technology/CN=smtp.mail.yahoo.com"
<~  220 smtp.mail.yahoo.com ESMTP ready
 ~> EHLO www.example.net
<~  250-smtp.mail.yahoo.com
<~  250-PIPELINING
<~  250-SIZE 41697280
<~  250-8 BITMIME
<~  250 AUTH PLAIN LOGIN XOAUTH2 XYMCOOKIE
 ~> AUTH PLAIN AGFhQxsZXguaGhMGdATGV4X2hoYtYWlsLmNvbQBS9TU1MjQ=
<~  235 2.0.0 OK
 ~> MAIL FROM:<user@yahoo.com>
<~  250 OK , completed
 ~> RCPT TO:<user@gmail.com>
<~  250 OK , completed
 ~> DATA
<~  354 Start Mail. End with CRLF.CRLF
 ~> Date: Wed, 17 Feb 2016 10:08:28 +0000
 ~> To: user@gmail.com
 ~> From: user@yahoo.com
 ~> Subject: Test message
 ~> X-Mailer: swaks v20130209.0 jetmore.org/john/code/swaks/
 ~>
 ~> Hello world
 ~>
 ~>
 ~> .
<~  250 OK , completed
 ~> QUIT
<~  221 Service Closing transmission
=== Connection closed with remote host.

我过去五年一直使用swaks通过gmail发送nagios的电子邮件通知,没有遇到任何问题。

4

根据已有答案,这是一份关于使用GMail帐户从命令行发送自动化电子邮件的逐步指南,在不泄露密码的情况下。

要求

首先,安装以下软件包:

这些说明假设您使用Linux操作系统,但应该很容易移植到Windows(通过Cygwin或本机等效程序)或其他操作系统。

认证

将以下shell脚本保存为authentication.sh

#!/bin/bash

# Asks for a username and password, then spits out the encoded value for
# use with authentication against SMTP servers.

echo -n "Email (shown): "
read email
echo -n "Password (hidden): "
read -s password
echo

TEXT="\0$email\0$password"

echo -ne $TEXT | base64

将它变为可执行文件并按以下方式运行:

chmod +x authentication.sh
./authentication.sh

当提示时,请提供您的电子邮件地址和密码。这将类似于:

Email (shown): bob@gmail.com
Password (hidden): 
AGJvYkBnbWFpbC5jb20AYm9iaXN0aGViZXN0cGVyc29uZXZlcg==

复制最后一行 (AGJ...==),因为这将用于认证。

通知

将以下expect脚本保存为notify.sh(注意第一行引用了expect程序):

#!/usr/bin/expect

set address "[lindex $argv 0]"
set subject "[lindex $argv 1]"
set ts_date "[lindex $argv 2]"
set ts_time "[lindex $argv 3]"

set timeout 10
spawn openssl s_client -connect smtp.gmail.com:465 -crlf -ign_eof 

expect "220" {
  send "EHLO localhost\n"

  expect "250" {
    send "AUTH PLAIN YOUR_AUTHENTICATION_CODE\n"

    expect "235" {
      send "MAIL FROM: <YOUR_EMAIL_ADDRESS>\n"

      expect "250" {
        send "RCPT TO: <$address>\n"

        expect "250" {
          send "DATA\n"

          expect "354" {
            send "Subject: $subject\n\n"
            send "Email sent on $ts_date at $ts_time.\n"
            send "\n.\n"

            expect "250" {
                send "quit\n"
            }
          }
        }
      }
    }
  }
}

请执行以下更改:

  1. 使用认证脚本生成的认证代码覆盖 YOUR_AUTHENTICATION_CODE
  2. YOUR_EMAIL_ADDRESS 更改为用于生成认证代码的电子邮件地址。
  3. 保存文件。

例如(请注意,尖括号保留了电子邮件地址):

send "AUTH PLAIN AGJvYkBnbWFpbC5jb20AYm9iaXN0aGViZXN0cGVyc29uZXZlcg==\n"
send "MAIL FROM: <bob@gmail.com>\n"

最后,按照以下方式将notify脚本变为可执行文件:
chmod +x notify.sh

发送电子邮件

可以使用以下命令从命令行发送电子邮件:

./notify.sh recipient@domain.com "Command Line" "March 14" "15:52"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接