msmtp

来自 ArchWiki

msmtp 是一个非常简单易用的 SMTP 客户端,具有相当完整的 sendmail 兼容性。

安装

安装 msmtp 软件包。此外,安装 msmtp-mta,它会创建一个指向 msmtp 的 sendmail 别名。

基本设置

从 msmtp 1.8.6 版本开始,你可以将用户配置文件放置在 ~/.msmtprc$XDG_CONFIG_HOME/msmtp/config。以下是一个 msmtp 配置示例(该文件基于位于 /usr/share/doc/msmtp/msmtprc-user.example 的用户示例文件;系统配置文件位于 /etc/msmtprc,其对应的示例文件位于 /usr/share/doc/msmtp/msmtprc-system.example)。

提示: 如果使用 Gmail,你需要执行以下操作之一:
~/.msmtprc
# Set default values for all following accounts.
defaults
auth           on
tls            on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        ~/.msmtp.log

# Gmail
account        gmail
host           smtp.gmail.com
port           465
tls_starttls   off
from           username@gmail.com
user           username
password       plain-text-password

# A freemail service
account        freemail
host           smtp.freemail.example
from           joe_smith@freemail.example
...

# Set a default account
account default: gmail
注意: 如果你正在使用 SSL/TLS 并收到 “Server sent empty reply” 错误消息,请参阅 #服务器发送空回复

用户 配置文件必须显式设置为所有者可读/可写,否则 msmtp 将会失败

$ chmod 600 ~/.msmtprc

为了避免以纯文本形式将密码保存在配置文件中,请使用 passwordeval 启动外部程序,或参阅下面的 #密码管理 章节。这个使用 GnuPG 的示例通常用于执行密码解密

echo -e "password\n" | gpg --encrypt -o .msmtp-gmail.gpg # enter id (email...)
警告: 大多数 shell 保存命令历史记录(例如 .bash_history .zhistory)。为了避免这种情况,请将 gpg 与 shell stdin 一起使用:gpg --encrypt -o .msmtp-gmail.gpg -r <email> -。结尾的破折号不是笔误,而是使 gpg 使用 stdin。运行该代码段后,输入你的密码,按 Enter 键,然后按 Control-d,以便 gpg 可以加密你的密码。
~/.msmtprc
passwordeval    "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.msmtp-gmail.gpg"

OAuth2 设置

当站点配置不支持或不希望使用基本的用户名/密码身份验证时,可以使用 OAuth2 来安全地验证 msmtp。

注意: 这篇文章 解释了 Gmail 现在允许的极度受限的功能。

oama

msmtp 本身缺乏续订或授权 OAuth2 凭据的能力。一个全面的解决方案是使用 oama 实用程序,该实用程序为 IMAP/SMTP 客户端提供 OAuth2 凭据的续订和授权功能。

要使用 oama,安装 oama-binAUR 并配置 msmtp 以使用它

   # account at Google with oauth2 access                                    
   account YOUR_EMAIL_NAME@gmail.com
   from YOUR_EMAIL_NAME@gmail.com
   user YOUR_EMAIL_NAME@gmail.com
   auth oauthbearer
   passwordeval oama access YOUR_EMAIL_NAME@gmail.com
   host smtp.gmail.com
   port 587
   tls on
   tls_trust_file /etc/ssl/certs/ca-certificates.crt

访问令牌续订在后台自动发生,对用户透明。

使用 mail 命令

要使用 mail 命令发送邮件,你必须安装 s-nail 软件包,它也提供了 mailx 命令。你还需要提供一个与 sendmail 兼容的 MTA,可以通过安装 msmtp-mta(它将 sendmail 符号链接到 msmtp)或通过编辑 /etc/mail.rc 来设置 sendmail 路径

/etc/mail.rc
set mta=/usr/bin/msmtp

每个想要发送邮件的用户的主目录中都需要一个 .msmtprc 文件,或者可以使用系统范围的 /etc/msmtprc

msmtp 也理解别名。将以下行添加到 msmtprc 的 defaults 部分或你的本地配置文件中

/etc/msmtprc
aliases               /etc/aliases

并在 /etc 中创建一个别名文件

/etc/aliases
# Example aliases file
     
# Send root to Joe and Jane
root: joe_smith@example.com, jane_chang@example.com
   
# Send everything else to admin
default: admin@domain.example

测试功能

account 选项 (--account=,-a) 告知要使用哪个帐户作为发件人

$ echo "hello there username." | msmtp -a default username@domain.com

或者,发送主题和正文

$ printf "Subject: Test\n\nhello there username." | msmtp -a default username@domain.com

或者,地址在一个文件中

To: username@domain.com
From: username@gmail.com
Subject: A test

Hello there.
$ cat test.mail | msmtp -a default <username>@domain.com
提示: 你可以使用 --read-envelope-from 而不是 -a default 来根据你要发送的邮件中的 From: 字段自动选择帐户。你也可以使用 --read-recipients,-t 从邮件的 To、Cc 和 Bcc 标头中读取收件人地址,以及命令行中给出的收件人。

Cronie 默认邮件客户端

本文或章节已过时。

原因: Arch 使用 systemd/Timers 而不是 cronie(在 Talk:Msmtp 中讨论)

要使 Cronie 使用 msmtp 而不是 sendmail,请确保安装了 msmtp-mta,或编辑 cronie.service systemd 单元

/etc/systemd/system/cronie.service.d/msmtp.conf
[Service]
ExecStart=
ExecStart=/usr/bin/crond -n -m '/usr/bin/msmtp -t'

然后你必须告诉 cronie 或 msmtp 你的电子邮件地址。一种实现此目的的方法是将其添加到 msmtp 配置中

  1. 添加到 /etc/msmtprc
    aliases /etc/aliases
  2. 创建 /etc/aliases
    your_username: email@address.com

或者,你可以直接将其添加到 crontab 中

  • 在 crontab 中添加 MAILTO
    MAILTO=email@address.com
  • 在 crontab 中添加 MAILFROM
    MAILFROM=email@address-from-msmtp.com
最后一部分是必要的,以防止此错误
sendmail: server message: 550 5.7.1 Rejected due to unmatching envelope and header sender.

密码管理

msmtp 的密码 可以存储 在纯文本、加密文件或密钥环中。

GNOME Keyring

msmtp 本机支持将密码存储在 GNOME Keyring 中。按照链接的 wiki 页面上的描述设置密钥环,并安装 libsecret。然后,通过运行以下命令存储密码

secret-tool store --label=msmtp host smtp.your.domain service smtp user yourusername

msmtp 现在应该会自动找到密码。

GnuPG

可以省略 password 指令。在这种情况下,如果相关帐户的 auth 设置为除 off 之外的合法值,则从交互式 shell 调用 msmtp 将在发送邮件前询问密码。如果 msmtp 由另一种类型的应用程序(例如 Mutt)调用,则不会提示。对于这种情况,可以使用 --passwordeval 参数来调用外部密钥环工具,如 GnuPG

为此,设置 GnuPG,包括 gpg-agent,以避免每次都输入密码。然后,为 msmtp 创建一个加密的密码文件,如下所示。创建一个权限为 700 的安全目录,该目录位于 tmpfs 上,以避免将未加密的密码写入磁盘。在该目录中创建一个包含邮件帐户密码的纯文本文件。然后,使用你的私钥加密该文件

$ gpg --default-recipient-self -e /path/to/plain/password

删除纯文本文件,并将加密文件移动到最终位置,例如 ~/.mail/.msmtp-credentials.gpg。在 ~/.msmtprc 中添加

~/.msmtprc
passwordeval  "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.mail/.msmtp-credentials.gpg"

通常,这足以在例如从 Mutt 发送消息时显示 GUI 密码提示。如果无法发出 gpg 提示输入密码,请先启动 gpg-agent。启动代理的一个简单技巧是在你的 muttrc 中使用反引号 `command` 语法执行外部命令。例如,你可以将以下内容放在你的 muttrc 中

muttrc
set my_msmtp_pass=`gpg -d mypwfile.gpg`

Mutt 将在启动时执行此操作,gpg-agent 将缓存你的密码,msmtp 将会很高兴,你可以发送邮件。

注意: 如果你这样做,你将必须在 gpg-agent 清除密码后重启 mutt 才能再次开始发送电子邮件。

另一种方法是将密码放在 ~/.netrc 中,该文件可以充当 msmtp、OfflineIMAP 和相关工具的公共池。

pass

你可以将你的凭据存储在 pass 密码管理器中。

如果你使用你的主密码(通常存储在你的 pass 文件的第一行)登录到你的 SMTP 服务器,你可以将以下内容添加到你的 .msmptrc

~/.msmtprc
passwordeval   "pass your_email_password_entry | head -n1"

如果你使用 Gmail,并且已设置 应用密码,则以下配置更适合你。将你的应用密码保存在你的 pass 密码文件中,但带有 msmtp: 前缀

your_email_password_entry
your_main_password

login: your_username
url: the_url_of_your_email
msmtp: your_msmtp_app_password

然后将以下内容添加到你的 .msmptrc

~/.msmtprc
passwordeval   "pass your_email_password_entry | awk '/^msmtp:/ { print $2; }'"

在任何一种情况下,尝试使用 msmtp 发送电子邮件都会触发 pass,如果你最近没有输入过 pass 主密码,则可能会要求你输入。

其他

离线使用 msmtp

虽然 msmtp 很棒,但它要求你在线才能使用它。这对于使用间歇性 Internet 连接或拨号用户的笔记本电脑用户来说并不理想。已经编写了几个脚本来弥补这一事实,统称为 msmtpqueue。

这些脚本安装在 /usr/share/doc/msmtp/msmtpqueue 下。你可能想要将这些脚本复制到你计算机上的方便位置(/usr/local/bin 是一个不错的选择)。

最后,更改你的 MUA 以在使用发送电子邮件时使用 msmtp-enqueue.sh 而不是 msmtp。默认情况下,排队的消息将存储在 ~/.msmtpqueue 中。要更改此位置,请更改脚本中的 QUEUEDIR=$HOME/.msmtpqueue 行(或删除该行,并在 .bash_profile 中导出 QUEUEDIR 变量,如下所示:export QUEUEDIR="$XDG_DATA_HOME/msmtpqueue")。

当你想要发送任何已创建和排队的邮件时,运行

$ /usr/local/bin/msmtp-runqueue.sh

如果手动执行此操作,将 /usr/local/bin 添加到你的 PATH 可以节省一些击键次数。脚本附带的 README 文件包含一些有用的信息,建议阅读。

Vim 语法高亮

msmtp 源代码发行版包含一个用于 Vimmsmtprc 语法高亮脚本,该脚本位于 /usr/share/vim/vimfiles/syntax/msmtp.vim。文件类型不会自动检测。启用它的最简单方法是在文件顶部或底部添加一个 modeline,即

# vim:filetype=msmtp

使用 PHP 通过 msmtp 发送邮件

在你的 php.ini 中查找 sendmail_path 选项,并像这样编辑

sendmail_path = "/usr/bin/msmtp -C /path/to/your/config -t"

请注意,如果你计划将 msmtp 用作 php 或类似程序的 sendmail 替代品,则不能使用用户配置文件(即:~ / 下的配置文件)。在这种情况下,只需创建 /etc/msmtprc,并删除你的用户配置(或者如果你计划将其用于其他用途,则不删除)。还要确保你使用的任何程序(php、django 等)都可以读取它。

来自 msmtp 手册:用户配置文件中定义的帐户将覆盖系统配置文件中的帐户。用户配置文件必须具有不超过用户读/写的权限

因此,不可能在 ~ / 下有一个 conf 文件,并且仍然可以被 php 用户读取。

要对其进行测试,请将此文件放在你的启用 php 的服务器中,或使用 php-cli。

<?php
mail("your@email.com", "Test email from PHP", "msmtp as sendmail for PHP");
?>

php-fpm 将无法发送邮件,并记录警告:PHP Warning: mail(mail.log): failed to open stream,除非你将 /etc/msmtprc 的权限设置为用户读/写 (600)。

故障排除

TLS 问题

如果你看到以下消息

msmtp: TLS certificate verification failed: the certificate hasn't got a known issuer

这可能意味着你的 tls_trust_file 不正确。

只需按照 精细手册 进行操作。它解释了如何找出给定 smtp 服务器的服务器证书颁发者。然后,你可以浏览 /usr/share/ca-certificates/ 目录,以查看你需要的证书是否碰巧在那里。如果不是,你将必须自行获取证书。如果你正在使用自己的证书,则可以通过将以下内容添加到你的 ~/.msmtprc 中来使 msmtp 信任它

tls_fingerprint <SHA1 (recommended) or MD5 fingerprint of the certificate>

如果你尝试通过 Gmail 发送邮件并收到此错误,请查看 线程,或直接使用上面的第二个 Gmail 示例。

如果你完全绝望,但 100% 确定你正在与正确的服务器通信,则始终可以暂时禁用证书检查

$ msmtp --tls-certcheck off

如果你看到以下消息

msmtp: TLS handshake failed: the operation timed out

你可能会受到此 错误 的影响。使用 --with-ssl=openssl 重新编译(msmtp 默认使用 GnuTLS 编译)。

服务器发送空回复

如果你收到 “server sent empty reply” 错误,这可能意味着邮件服务器不支持端口 587 上的 STARTTLS,但需要端口 465 上的 TLS。

要让 msmtp 使用端口 465 上的 TLS,请将以下行添加到 ~/.msmtprc

tls_starttls off

Zoho SMTP 服务器

当邮件在邮件标头和邮件正文之间没有空行时,也可能发生在 Zoho SMTP 服务器上(请参阅 Debian 错误 #917260)。解决此问题的方法是在两者之间添加一个额外的空格

"test-header\n\ntest-body"

GSSAPI 问题

如果你收到以下错误

GNU SASL: GSSAPI error in client while negotiating security context in gss_init_sec_context() in SASL library.  This is most likely due insufficient credentials or malicious interactions.

尝试将你的 .msmtprc 文件中的 auth 设置更改为 plain,而不是 gssapi [1]

auth plain

信封未被接受

如果是以下情况

msmtp: envelope from address mail@server not accepted by the server
msmtp: server message: 530 5.5.1 Authentication Required.
msmtp: could not send mail (account default from /etc/msmtprc)

尝试启用身份验证,使用

auth on

或任何其他方法。