跳转至内容

S-nail

来自 ArchWiki

本文或本节需要在语言、wiki 语法或风格方面进行改进。请参阅 Help:Style 获取参考。

原因:非常冗长,大量代码,不遵循样式指南。(请在 Talk:S-nail 中讨论)

Arch Linux 使用 S-nail 作为其 POSIX mailx 的实现。S-nail 支持 MIME,并具有行编辑、S/MIME、SMTP、IMAP、POP3 等功能的扩展。Mailx 是 Unix 邮件系统的*用户端*,而*系统端*传统上由 sendmail 负责。S-nail 还可以直接发送到外部 SMTP 服务器,因此不需要本地 MTA。

安装

安装 s-nail 包。

示例用法

由于系统范围的配置文件(/etc/mail.rc)包含一些有用的标准,通过已安装的本地邮件传输代理(MTA),例如 sendmailpostfix,发送邮件可以非常简单,如下所示:

# echo 'Message body' | mailx --debug --subject='A subject' --attach=an_attachment.txt foo1@bar.example 'Foo2 <foo2@bar.example>'

使用 -d/--debug 标志将导致沙箱模拟运行。您可以通过设置变量 mta 来调整用作 MTA 的程序(通过 mta-argumentsmta-no-default-argumentsmta-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 命令行标志来创建自己的可重现设置。

使用 expandaddr 选项可以将邮件发送到文件和管道,无需 MTA 干预。

# 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 以避免模拟运行。它将 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) § 关于阅读邮件和交互模式 在寻找更多“快速提示”时值得一览。

在以下情况下,当 USERPASS 作为 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 tls-ca-dir=/etc/ssl/certs
set tls-ca-file=/etc/ssl/certs/ca-certificates.crt
set tls-ca-no-defaults
#set tls-ca-flags=partial-chain

# Do not use protocols older than TLS v1.2.
# Change this only when the remote server does not support it:
# CipherString: explicitly define the list of ciphers, which may
#   improve security, especially with protocols older than TLS v1.2.
#   See ciphers(1).  Possibly best to only use tls-config-pairs-HOST
#   (or -USER@HOST), as necessary, again..
#   Note that TLSv1.3 uses Ciphersuites= instead, which will join
#   with CipherString (if protocols older than v1.3 are allowed)
# Curves: especially with TLSv1.3 curves selection may be desired.
# MinProtocol,MaxProtocol: do not use protocols older than TLS v1.2.
#   Change this only when the remote server does not support it:
#   maybe use chain support via tls-config-pairs-HOST / -USER@HOST
#   to define such explicit exceptions, then, e.g.,
#     MinProtocol=TLSv1.1
set tls-config-pairs='\
     CipherString=TLSv1.2:!aNULL:!eNULL:@STRENGTH,\
     Curves=P-521:P-384:P-256,\
     Protocol=-ALL\, +TLSv1.2\, +TLSv1.3'

# Request strict TLL transport layer security checks
set tls-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>"
}
提示 在 Gmail 中启用两步验证,并为 S-nail 添加特定应用程序的密码,您将希望使用该密码而不是您的常规 Gmail 密码。

请注意,在 $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

在这种情况下,USERPASS 是明文,未进行 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 命令行选项进行模拟运行)

# 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)的标题列表以供显示,但 Print 命令不会,而是显示所有标题;Show 命令将打印原始消息内容。

默认情况下会打印当前消息(点),但就像许多其他命令一样,可以指定消息列表,这在手册章节 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 没有空格字符的消息。请注意,当搜索表达式等包含空格时,可能需要引用。

  • fileFile 打开一个新的邮箱,后者以只读模式打开。
  • newmail(取决于邮箱,检查新邮件并)打印新邮件的列表。
  • he (headers) 重新打印消息列表。
  • z- z+ z0 z$ 在标题显示中滚动(取决于您使用的终端,Home/End/PageUp/PageDown 键将是有效的别名)。
  • folders 显示当前设置的 folder 下的邮箱列表。
  • r 回复给定消息的所有收件人。
  • R 回复给定消息的发送者。
  • Lreply 对给定消息进行“邮件列表”回复。
  • movemv 移动(一条或多条)消息。
  • (un)flag 将(一条或多条)消息标记为(未)标记。
  • new 将(一条或多条)消息标记为未读。
  • seen 将(一条或多条)消息标记为已读。
  • P 打印(一条或多条)消息,包含所有标题。
  • p 打印(一条或多条)消息以及所有非忽略的标题。
  • show 打印(一条或多条)消息的原始消息内容。
  • writew 以原生格式将消息和附件下载到本地存储。

消息撰写

通过键入 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,而 OpenSSL 仅支持结构简单的 MIME 消息。

解决缺少 OpenPGP 支持的方法

S-nail 尚不支持 OpenPGP。但是,使用宏可以至少自动验证内联的 --clearsigned 消息,并且使用命令别名可以方便地使用它们:例如,在资源文件中使用以下内容,您只需键入 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 邮箱

以下仅为快速提示。也可以定义 folderinbox 指向 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

参见

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