S-nail
Arch Linux 使用 S-nail 作为其 POSIX mailx
的实现。S-nail 具有 MIME 功能,并扩展了行编辑、S/MIME、SMTP、IMAP、POP3 等功能。Mailx 是 Unix 邮件系统的用户端,而系统端传统上由 sendmail 承担。S-nail 也可以直接发送到外部 SMTP 服务器,因此不需要本地 MTA。
安装
使用示例
由于系统范围的配置文件 (/etc/mail.rc
) 引入了一些有用的标准,因此通过已安装的本地邮件传输代理 (MTA)(例如 sendmail 或 postfix)发送邮件可以像下面这样简单
# echo 'Message body' | mailx --debug --subject='A subject' --attach=an_attachment.txt foo1@bar.example 'Foo2 <foo2@bar.example>'
使用 -d
/--debug
标志会产生沙盒 dry-run。您可以通过设置变量 mta
来调整用作 MTA 的程序(通过 mta-arguments
、mta-no-default-arguments
、mta-argv0
进行微调)。
请参阅手册 mailx(1)。特别是,请参阅 mailx(1) § 发送邮件和非交互模式
# < /etc/passwd LC_ALL=C.UTF-8 mailx --debug -:/ --set=sendwait --set=ttycharset=utf8 --set=mta=/usr/bin/sendmail --subject='My password file!' -. 'Back <side@book>' # echo Message was passed successfully: $?
默认情况下,消息传递是异步的,mailx 会在准备好的消息传递给传递机制后立即退出,仅说明消息准备是否成功(或不成功)。但是,如果设置了 sendwait
选项,则启动的(内置或非内置)MTA 的退出状态将用作消息传递“成功”或“失败”状态。
-.
/--end-options
命令行选项将强制终止选项处理并打开消息发送模式。
如前面的示例所示,命令可以(并且应该)通过 LC_ALL=C.UTF-8
、-:/
/−−resource-files=/
从环境设置和配置文件中分离出来,并使用显式的 -S
/--set
和 -X
/--startup-cmd
命令行标志来创建其自身的可重现设置。
在没有 MTA 干预的情况下,使用 expandaddr
选项可以将消息发送到文件和管道
# echo bla | mailx --set=expandaddr --subject=test ./mbox.mbox # echo bla | mailx --set=expandaddr --subject=test '|cat >> ./mbox.mbox' # echo bla | mailx --set=expandaddr --subject=test -
可以为 expandaddr
赋值并用于地址验证。以下示例假设 somefile.pdf 存在。如上所述,应删除 -d
/--debug
以避免 dry run。它将 record
选项设置为用于记录所有传出邮件的文件,以便我们可以查看生成的邮件
# echo Body | \ > LC_ALL=C.UTF-8 mailx --debug -:/ --set=v15-compat --set=sendwait --set=ttycharset=utf8 \ > --set=from='Me <me@home>' \ > --set=expandaddr=fail,-all,+addr \ > --set=nosave --set=record=/tmp/out.mbox \ > --set=mimetypes-load-control \ > --startup-cmd='mimetype application/pdf pdf' \ > --attach=somefile.pdf --subject=Subject \ > -. '(foo2bar) <foo2@bar.example>' bob@hey.example # mailx --read-only --file /tmp/out.mbox
手册章节 mailx(1) § 入门 和 mailx(1) § 阅读邮件和交互模式 值得在寻找更多“速成”方法时浏览一下。
在以下情况中,当 USER 和 PASS 作为 URL 的一部分指定时(且仅在此情况下),它们必须进行 URL 百分号编码:mailx 提供了 urlcodec
命令来为您执行此操作
# printf 'urlcodec encode USER PASS\nx\n' | mailx -#
-#
用于 -#
/--batch-mode
。printf 以及 mailx 都受您的区域设置影响
# # In UTF-8: # printf 'urlcodec encode SPAß\nx\n' | mailx -# SPA%C3%9F # # In ISO-8859-1: # printf 'urlc enc SPAß\nx\n' | mailx -# SPA%DF
配置
配置文件是用户特定的 $HOME/.mailrc
和系统范围的 /etc/mail.rc
,后者位于 PKGBUILD 的 备份数组 中,因此将在 s-nail 升级后保留。本文中的所有其余示例均基于此配置模板,该模板仅设置了一些安全和发送模式基础知识
# All the examples require v15-compat! set v15-compat # Arch Linux-specific locations of certificates. # Since these are subject to the Arch Linux update mechanism, # use only those, do not try to load OpenSSL builtin ones. # And use the TLS specific set: see "man 8 update-ca-trust" #set ssl-ca-dir=/etc/ssl/certs set ssl-ca-file=/etc/ssl/certs/ca-certificates.crt set ssl-ca-no-defaults # Do not use protocols older than TLS v1.2. # Change this only when the remote server does not support it: # maybe use ssl-protocol-HOST (or -USER@HOST) syntax to define # such explicit exceptions, then, e.g. # ssl-protocol-USER@archlinux.org="-ALL,+TLSv1.2" set ssl-protocol=-ALL,+TLSv1.2 # Explicitly define the list of ciphers, which may improve security, # especially with protocols older than TLS v1.2. See ciphers(1). # This is an example: in reality it is possibly best to only use # ssl-cipher-list-HOST (or -USER@HOST), as necessary, again.. set ssl-cipher-list=TLSv1.2:!aNULL:!eNULL:@STRENGTH #set ssl-cipher-list="ALL:!aNULL:!eNULL:!MEDIUM:!LOW:!MD5:!RC4:!EXPORT" # Request strict transport security checks set ssl-verify=strict # Essential setting: select allowed character sets # (Have a look at the "Character sets" manual section) set sendcharsets=utf-8,iso-8859-1 # A very kind option: when replying to a message, first try to # use the same encoding that the original poster used herself! set reply-in-same-charset # When replying to or forwarding a message the comment and name # parts of email addresses are removed unless this variable is set set fullnames # When sending messages, wait until the Mail-Transfer-Agent finishs. set sendwait # Only use builtin MIME types, no mime.types(5) files. # That set is often sufficient, but look at the output of the # `mimetype' command to ensure this is true for you, too set mimetypes-load-control # Default directory where we act in (relative to $HOME if not absolute) set folder=mail # A leading "+" (often) means: under folder # record is used to save copies of sent messages, $DEAD is error storage # inbox: system mailbox, by default /var/mail/$USER: file % # $MBOX: secondary mailbox: file & set MBOX=+mbox.mbox record=+sent.mbox DEAD=+dead.mbox set inbox=+system.mbox # Define some shortcuts; now one may say, e.g., file mymbo shortcut mymbo %:+mbox.mbox \ myrec +sent.mbox # This is optional, but you should get the big picture # by reading the manual before you leave that off set from="Your Name <youremail@domain>" # Mailing-list specifics (manual: "Mailing lists"): set followup-to followup-to-honour=ask-yes reply-to-honour=ask-yes # And teach some non-subscribed / some subscribed lists, too mlist @xyz-editor.xyz$ @xyzf.xyz$ mlsubscribe ^xfans@xfans.xyz$
使用外部 SMTP 服务器发送邮件
要通过内置 SMTP(简单邮件传输协议)客户端将消息发送到外部 SMTP 服务器,必须设置或调整几个选项。根据需要将以下内容添加到上述配置中,更改粗体字符串。阅读手册章节 mailx(1) § 关于 URL 语法和凭据查找 是值得的。
# It can be as easy as # (Remember USER and PASS must be URL percent encoded) set mta=smtp://USER:PASS@HOST \ smtp-use-starttls # It may be necessary to set hostname and/or smtp-hostname # if the "SERVER" of smtp and "domain" of from do not match. # Reading the "ON URL SYNTAX.." and smtp manual entries may be worthwhile set mta=(smtp[s]/submission)://[USER[:PASS]@]SERVER[:PORT] \ smtp-auth=login[/plain]... \ smtp-use-starttls # E.g. here is a real life example of a very huge free mail provider # (Activate this account via mailx -AXooglX from the command line, # or use the ? acc[ount] XooglX command in interactive mode) account XooglX { # Localize options, forget them when changing the account localopts yes # (The plain smtp:// proto is optional) set mta=smtp://USER:PASS@smtp.gmXil.com smtp-use-starttls set from="Your Name <youremail@domain>" } # And here is a pretty large one which does not allow sending mails # if there is a domain name mismatch on the SMTP protocol level, # which would bite us if the value of from does not match, e.g., # for people who have a sXXXXeforge project and want to speak # with the mailing list under their project account (in from), # still sending the message through their normal mail provider account XandeX { localopts yes set mta=smtps://USER:PASS@smtp.yaXXex.ru:465 \ hostname=yaXXex.com smtp-hostname= set from="Your Name <youremail@domain>" }
请注意,当在 $HOME/.mailrc
中存储密码时,您应该使用 chmod 0600
设置适当的 权限。您还可以设置 netrc-lookup 选项,并将用户凭据存储在 $HOME/.netrc
(或 $NETRC)中;例如,这是一个实际示例,设置了 SMTP、POP3 以及 IMAP,并将所有用户凭据存储在那里
account XandeX { localopts yes set from="Your Name <youremail@domain>" wysh set netrc-lookup # netrc-pipe='gpg -qd ~/.netrc.gpg' set mta=smtps://smtp.yXXXXx.ru:465 \ smtp-hostname= hostname=yXXXXx.com set pop3-keepalive=240 shortcut pop pop3s://pop.yXXXXx.ru # Type xp to login to the POP3 account commandalias xp 'fi pop' set imap-keepalive=240 shortcut imap imaps://imap.yXXXXx.ru # Type xi to login to the IMAP account commandalias xi 'fi imap' }
并且,在 $HOME/.netrc
中
machine *.yXXXXx.ru login USER password PASS
在这种情况下,USER 和 PASS 是明文,而不是 URL 编码的。您可以进一步多样化,并使用加密密码存储。要相应地调整示例,只需使用 OpenPGP 加密您的 ~/.netrc
文件,并取消注释上面的 netrc-pipe
语句。可以像这样创建加密存储 ~/.netrc.gpg
# gpg -e .netrc # eval `gpg-agent --daemon --pinentry-program=/usr/bin/pinentry-curses --max-cache-ttl 99999 --default-cache-ttl 99999`
测试配置(使用 -d
/--debug
命令行选项进行 dry-run)
# echo test-body | mailx --verbose --verbose --account=XandeX --subject=test-subject some@where
交互式使用
在整个手册中,交互式使用被称为“撰写模式”。mailx(1) § 撰写模式。
Mailx 具有支持宽字形的命令行编辑器,具有历史记录功能和彩色消息显示支持。因为它力求符合 POSIX 标准,所以在交互式使用之前必须调整一些设置,但这并不能阻止所有描述。阅读 mailx(1) 是不可避免的,但至少在示例配置之上添加以下内容
# (The global configuration /etc/mail.rc provides some commented basics; # in particular it shows all options that POSIX mandates as defaults.) # Start into interactive mode even if the system mailbox is empty or # does not exist. mailx will exit immediately without that one set emptystart # When composing a message, start directly into $EDITOR set editalong # Start $PAGER when a message is longer than VALUE lines; # without VALUE: screen $LINES set crt= # A nicer prompt for a modern terminal wysh set prompt='?\${?}!\${!}[\${account}#\${mailbox-display}]? ' # Add more entries to the history, and make that persistent set history-gabby history-file=+.s-nailhist # When printing messages, show only these headers # (Easier to retain what you want than to ignore # what you do not; use Print to see all headers and Show # to see the raw message content) retain date from to cc subject # Try to get around weird MIME attachment specifications # (This option can take a value, see the manual for more) set mime-counter-evidence=0xE # Display HTML parts inline, nicer than what the builtin viewer can achieve #set pipe-text/html='@* lynx -stdin -dump -force_html' # Learn another mimetype mimetype model/vrml wrl vrml # Create some new commands so that, e.g., `ls /tmp' will.. commandalias ls !ls -latro commandalias ps !ps axu
进入后,使用 list 打印所有可用的内置命令。键入 `?X' 尝试展开 "X" 并打印帮助字符串;由于 mailx 允许缩写所有命令,因此这有时很方便,例如,尝试 ?h、?he 和 ?hel ... 命令 help 将打印最常用命令的简短摘要,如果设置了变量 verbose
,则会更多。
用法
当启动进入交互模式时,会打印初始打开的邮箱内容的摘要,就像通过 headers
命令一样。在标头显示中,消息被赋予数字(从 1 开始),这些数字唯一标识消息。可以使用 print
命令打印消息,或简写:p
。p
尊重要显示的标头的 retain
(或 ignore
)列表,而 P
rint 命令则不会,并且会显示所有标头;Sh
ow 命令将打印原始消息内容。
默认情况下,打印当前消息(点),但就像许多其他命令一样,可以指定消息列表,如手册章节 mailx(1) § 指定消息 中所述;例如,p:u
将显示所有未读消息,p.
将打印当前消息(点),p 1 5
将打印消息 1 和 5,p-
和 p+
将分别打印上一条和下一条消息。请注意,在空行中简单地键入 RETURN 就像 next
(n
) 一样,因此会打印下一条消息。
from
命令对于概述很有用,例如,f '@<@arch linux
将打印所有消息的标头摘要,这些消息在某些消息标头中包含字符串“arch linux”,而 f '@arch linux
将仅匹配主题中包含“arch linux”的消息;最后,正则表达式 f @^A[^[:space:]]+
查找主题以 A 字符开头的所有消息,并且在该 A 字符之后没有空格字符。请注意,当搜索表达式等中存在空格时,可能需要引用。
file
和File
打开一个新的邮箱,后者以只读模式打开newmail
(取决于邮箱,检查新邮件并)打印新消息的列表he
(headers)重新打印消息列表z-
z+
z0
z$
滚动浏览标头显示(取决于您使用的终端,Home/End/PageUp/PageDown 键将是可用的别名)folders
显示当前设置的folder
下的邮箱列表r
回复给定消息的所有收件人R
回复给定消息的发送者Lreply
“邮件列表”回复给定消息move
或mv
移动(一条或多条)消息(un)flag
将(一条或多条)消息标记为(未)标记new
将(一条或多条)消息标记为未读seen
将(一条或多条)消息标记为已读P
打印(一条或多条)消息以及所有标头p
打印(一条或多条)消息以及所有非忽略标头show
打印(一条或多条)消息的原始消息内容write
或w
以本机格式将消息和附件下载到本地存储
消息撰写
撰写通过键入 mail user@host
或回复消息开始。当您输入 $EDITOR
(假设设置了 editalong
)时,您将发现自己处于本机编辑器中,您可以在其中使用波浪号转义符执行许多操作(通过 ~?
获得简短帮助)。特别感兴趣的是 ~@
,它允许交互式编辑附件列表,或者,当给定参数时,添加(一个或多个)(逗号分隔的列表)附加附件,以及 ~^
,它是一个多路复用器命令,提供对消息的一些控制,例如,创建自定义标头。
要发送邮件,请使用 Ctrl+d
发送 EOT 信号或键入 ~.
在单独的一行上。
使用 S/MIME
该手册包含有关如何创建证书等的逐步示例 (mailx(1) § 使用 S/MIME 签名和加密消息 以及 mailx(1) § S/MIME 逐步指南)。假设您已经拥有私钥和签名证书,只需创建我们需要的配对文件
# cat private-key.pem signed-certificate.pem > ~/pair.pem
并通过以下方式设置 S-nail
set smime-sign-cert=~/pair.pem \ smime-sign-message-digest=SHA256 \ smime-sign
从现在开始,发送的任何消息都将被签名。默认消息摘要将是 SHA1,这是 RFC:5751 要求的。请注意,S/MIME 始终相对于变量 from 的设置工作,因此最好将上述设置放在 account
中。verify
命令验证 S/MIME 消息,但请注意,S/MIME 解密和验证目前完全基于 OpenSSL,它仅支持具有简单 MIME 结构的消息。
OpenPGP 支持缺失的变通方法
S-nail 尚不支持 OpenPGP。但是,使用宏,至少可以自动验证内联 --clearsign
签名的消息,并且使用命令别名,它们的用法变得方便:例如,在资源文件中使用以下内容,您只需键入 V
即可验证 clearsigned 消息
define V { \localopts yes; \wysh set pipe-text/plain=$'@*#++=@\ < "${MAILX_FILENAME_TEMPORARY}" awk \ -v TMPFILE="${MAILX_FILENAME_TEMPORARY}" \'\ BEGIN{done=0}\ /^-----BEGIN PGP SIGNED MESSAGE-----/,/^$/ {\ if(done++ != 0)\ next;\ print "--- GPG --verify ---";\ system("gpg --verify " TMPFILE " 2>&1");\ print "--- GPG --verify ---";\ print "";\ next;\ }\ /^-----BEGIN PGP SIGNATURE-----/,/^-----END PGP SIGNATURE-----/ {\ next;\ }\ {print}\ \;\ print } define RK { !printf 'Key IDs to gpg --recv-keys: ';\ read keyids;\ gpg --recv-keys ${keyids}; } commandalias V '\'call V commandalias RK '\call RK'
使用 IMAP 邮箱
以下只是一些快速提示。还可以定义 folder 和 inbox 以指向 IMAP 服务器文件夹,例如。支持国际化名称。
set v15-compat # or many servers will expire the session set imap-keepalive=240 set imap-cache=~/.imap_cache
# You may want to define shortcuts to folders, for example: shortcut myimap "imaps://USER:PASS@server:port" set inbox=myimap