跳转至内容

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
...

# Accounts can inherit info from another account
account        postmasterfreemail : freemail
from           postmaster*@freemail.example

# Set a default account
account default: gmail
注意 如果您在使用 SSL/TLS 时收到“服务器发送了空回复”错误消息,请参阅 #服务器发送了空回复

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

$ chmod 600 ~/.msmtprc

为避免将密码以明文形式保存在配置文件中,请使用 passwordeval 调用外部程序,或参阅下面的 #密码管理 部分。以下使用 Gnu PG 的示例常用于解密密码。

echo -e "password\n" | gpg --encrypt -o .msmtp-gmail.gpg # enter id (email...)
警告 大多数 Shell 会保存命令历史(例如 .bash_history .zsh_history)。为避免这种情况,请使用 gpg 并通过 shell stdin:gpg --encrypt -o .msmtp-gmail.gpg -r <email> -。最后的连字符不是拼写错误,而是指示 gpg 使用 stdin。运行此代码片段后,输入您的密码,按 Enter,然后按 Ctrl-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。启动代理的一个简单技巧是使用反引号 `command` 语法在您的 muttrc 中执行外部命令。例如,您可以将以下内容放在您的 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 很棒,但它要求您在线才能使用。这对于连接不稳定的笔记本电脑用户或拨号用户来说并不理想。已经编写了几个脚本来解决这个问题,统称为 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 作为 sendmail 的替代品与 php 或类似工具一起使用,则不能使用用户配置文件(即 ~/ 下的配置文件)。在这种情况下,只需创建 /etc/msmtprc,然后删除您的用户配置文件(如果您打算将其用于其他用途,则不必删除)。还要确保您正在使用的工具(php、django 等)可以读取它。

来自 msmtp 手册:用户配置文件中定义的账户会覆盖系统配置文件中的账户。用户配置文件必须只有用户读/写权限

因此,不可能拥有一个位于 ~/ 下的配置文件,同时又能被 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
msmtp: TLS certificate verification failed: The certificate is NOT trusted. The certificate issuer is unknown.

这很可能意味着您的配置文件中的 tls_trust_file 参数不正确。

只需遵循优秀的文档。它会解释如何找出给定 smtp 服务器的服务器证书颁发者。然后,您可以探索 /usr/share/ca-certificates/ 目录,看看您是否碰巧在那里找到了所需的证书。如果没有,您将不得不自己获取证书。如果您使用自己的证书,可以通过将以下内容添加到您的 ~/.msmtprc 来让 msmtp 信任它:

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

如果用户拥有服务器使用的证书,并且该证书存储在 PEM 文件中,他可以使用 openssl 找到存储的证书指纹。

openssl x509 -in CERT.pem -inform PEM -fingerprint

如果您尝试通过 Gmail 发送邮件并收到此错误,请查看线程,或者只需使用上面提供的第二个 Gmail 示例。

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

$ msmtp --tls-certcheck off

如果您看到以下消息:

msmtp: TLS handshake failed: the operation timed out

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

服务器发送了空回复

如果您收到“服务器发送了空回复”错误,这可能意味着邮件服务器不支持在端口 587 上使用 STARTTLS,而是需要通过端口 465 使用 TLS。

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

tls_starttls off

Zoho SMTP 服务器

当邮件在邮件头和邮件正文之间没有空行时,也可能在 Zoho SMTP 服务器上发生这种情况(参见 Debian bug #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.

尝试将您的 auth 设置从 gssapi 更改为 plain,而不是在您的 .msmtprc 文件中[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

或任何其他方法。

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.