Jari的Procmail提示页面

作者:Jari Aalto。

目录

1.0文档ID
2.0 Procmail指针
3.0干运行测试
要记住的事情
5.0 Procmail标志
6.0匹配和正则表达式(正则表达式)
7.0变量
8.0建议和杂项
9.0得分
10.0正式使用
11.0保存邮件列表邮件
12.0 Procmail,MIME和HTML
13.0简单Recipe示例
14.0杂项Recipe
15.0 Procmail和PGP
16.0包含使用
17.0邮件列表服务器
18.0常见问题
19.0技术性事项
20.0 Emacs Procmail软件
21.0 RFC,请求注释
22.0电子邮件标题简介
23.0消息头

1.0文档ID

1.1总则

$ Id:pm-tips.txt,v 2.28 2004/10/06 13:55:39 jaalto Exp $
$ URL: http : //pm-doc.sourceforge.net/ $
$ UrlLinksLastChecked:2002-07-11 $

这是一个Procmail Tips页面:一组procmailRecipe,说明,howtos。 该文档还包含指向procmail邮件列表的URL指针和与互联网UBE打交道的站点。 Procmail是强大的邮件处理工具,这里已经有大量的空间用于讨论UBE(又名垃圾邮件)及其本质。 您还将发现许多其他有趣的课程,讨论互联网邮件一般:邮件头,MIME和RFC。 本文档的另一部分专用于Emacs和Emacs插件包Gnus.el,因为Emacs是您可以用来处理邮件和新闻阅读的最佳工具。 现在,Emacs也可以在Windows平台上使用。 这并不是说现有的Unix elm(1),mutt(1)或pine(1),slrn(1)邮件/新闻程序是坏的,与Emacs相比,它们的功能有限,通常与Unix平台相关。 最后,对于你的祝福或诅咒( 微笑 ),作者碰巧知道Emacs。 提示是从procmail讨论列表,comp.mail.misc和作者自己的procmail经验中编译的。

本文不打算教你procmail的基础知识,而是必须熟悉procmail手册页。 Procmail手册主要存在于Unix / Linux平台上,如果您使用Windows操作系统,请参阅Cygwin http://www.cygwin.com/

您可能想在本页面之前阅读Nancy'sEra的 procmail FAQ页面。 Ther是丰富的有用的procmail链接和指向处理邮件的Unix程序的指针。 如果您在本文档中发现错误或改进内容,请发送邮件至本文档的维护者。

如果任何提及的网址不存在,您仍然可以使用WWW搜索(例如http://www.google.com/

1.2什么是Procmail?

[常见问题] Procmail是一个邮件处理实用程序,可以帮助您过滤邮件,根据发件人,主题行,邮件长度,邮件中的关键字等对邮件进行排序,实现一个ftp-by-mail服务器,更多。 Procmail也是您的MDA的完全替代品。 (如果这并不意味着你,你可能不想知道。)Procmail在Unix下运行。 请参阅无限油墨的邮件过滤和机器人页面,了解有关各种其他平台的相关实用程序的信息,以及竞争的Unix程序(也没有那么多)。

1.3缩写和谢谢

人和文件,缩写,所使用的标记,都不是特定的顺序。

[stephen] Stephen R. van den Berg,Procmail的作者最后一次通过使用地址srb@cuci.nl从stephen 1997-08在procmail邮件列表中听到 。 1998年以后,由于他的定期工作活动和时间不足,他提名Philip Guenther为Procmail开发的负责人。

[aaron] Aaron Schrab aaron + procmail AT schrab com
[alan] Alan K. Stebbens alan.stebbens AT openwave com
丹麦史密斯丹尼尔史密斯AT WriteMe dt com
大卫·汤姆金·达蒂埃AT panix com
[ed] Edward J. Sabol sabol AT alderaan gsfc nasa gov
[elijah] Eli有胡子的过程在qz小脖子我们
[hal] Hal Wine hal AT dtor com
[jari] Jari Aalto jari aalto AT poboxes dt com
[philip]菲利普·金特
理查德 ·卡贝尔
[sean] Sean B. Straw PSE-L AT mail professional org
[ Timothy ] Timothy J Luoma luomat + procmail AT luomat peak org
Walter Dnes waltdnes AT interlog com

[FAQ] Procmail常见问题时代AT iki.fi
[手册]从一些procmail手册页引用
[维护者]截至2000-09年度,维护者是[jari]
#broken-link Link不再存在。 需要更换

一个大谢谢你所有这些人:

  • 1999-06-16 Mark Seiden mis@seiden.com做了一个有力的工作来校对v1.74。 他发出了大量的105k wpatch许多编辑修正。 我的全心全意谢谢你,马克。
  • 1999-01-08 Steven Alexander stevena@teleport.com认为一个小的perl脚本可以帮助我更容易地修复拼写错误。 该脚本比我自己更好的修正程序。 谢谢。 (自己是一个Perl程序员,我应该想到这个laready 微笑
  • 1999年Guido.Van.Hoecke@se.bel.alcatel.be获得1.48,发送了一个巨大的55k补丁来纠正许多英文错误。 非常感谢Guido。
  • 1998-10-28 Richard Kabel rkabel@sequent.com发送大量补丁来纠正语言,并提供了极好的改进意见。 感谢Guido花时间。
  • 1998年Era Eriksson证明阅读v1.12并发送了许多更正。
  • Karl E. Vogel vogelke@c17mis.region2.wpafb.af.mil发送了许多新的反垃圾邮件链接,以添加到文档中。
  • 1998 John Gianni jjg@cadence.com发送一些不错的Recipe:一个现在在procmail模块列表和其他想法我添加到这个提示文件。
  • 1998年Tim Potter tpot@zip.com.au有一个备用的时刻与v1.27,并发出大量的拼写更正。 谢谢。

1.4版本信息

这是文本文件的版本和文件大小日志,这给您一些估计如何文档演变。

      v2.27   2004-10-10  516  Spam related things removed.
v2.16 2002-08-31 596 Removed old UBE pointers.
v2.13 2002-08-13 596 Removed old UBE pointers.
v2.5 2002-02-01 608 Spelling checked with Emacs ispell
v2.2 2002-01-28 608 URL links checked and updated
v2.0 2001-08-09 608 http://pm-doc.sourceforge.net opened.
v1.77 1999-12-27 603 Netscape spam filters added
v1.76 1999-10-01 602 Mark Seiden's patch applied. Now under CVS.
v1.74 1999-04-26 599 document moved to www.procmail.org
v1.72 1999-04-21 597 Links corrected
v1.71 1999-03-29 597 Ricochet -- Perl script to fight UBE
v1.70 1999-02-26 592 procmail's Y2K compliance
v1.69 1999-02-23 590 RFC and using MIME in Usenet postings
v1.68 1998-01-29 587 Added "Lua" language pointer
v1.67 1998-01-07 579 Eli's procmail recipes in module section
v1.66 1998-12-14 578 Philip took care of bugs/patches listing
v1.64 1998-11-26 602 More Richard's comments integrated
v1.63 1998-10-30 595 Richard's english correction patch
v1.60 1998-10-21 591 UMASK, .forward if procmail already is LDA
v1.58 1998-10-12 583 SmartList and other MLM software discussed
v1.57 1998-10-06 575 PLUS addr. Convert HTML body to text
v1.55 1998-08-29 565 Fetching fields with formail -x
v1.53 1998-08-24 554 Procmail doesn't pass 8bit characters
v1.52 1998-08-24 553 Flag c forking study, procmail wish list
v1.51 1998-08-18 541 Small changes. MIME notes
v1.49 1998-08-10 529 Guido.Van.Hoeck's 55k patch applied
v1.46 1998-06-24 526 Added live urls to procmail archive
v1.45 1998-06-23 521 All recipes checked by eye. Many fixes.
v1.44 1998-06-19 516 Detecting mailing lists with pm-jalist.rc
v1.41 1998-06-17 510 How to disable recipe quickly with
v1.36 1998-04-03 493 Includerc rewritten, plus addressing
v1.34 1998-04-02 488 ORing and supreme scoring added
v1.32 1998-03-23 471 All recipes checked (by eye)
v1.31 1998-03-10 469 Better ordering: ORing rules discussed
v1.29 1998-01-30 429 "regexp" section rewrite.
v1.24 1997-12-30 415 up till 1996-12 is now included
v1.17 1997-12-09 343 up till archive 1996-07 now included
v1.14 1997-11-25 260
v1.13 1997-11-08 218 Era's correction suggestions.
v1.10 1997-10-13 181 archive file 1995-10's tips included
v1.9 1997-10-11 142
v1.8 1997-10-01 127
v1.6 1997-09-18 94
v1.5 1997-09-16 76
v1.05 1997-09-14 53
v1.01 1997-09-13 46 (k)

1.5文件布局和维护

为了能够在每个可能的平台中维护此文档,本文档的基本版本保存为文本格式,可轻松访问,无需特殊编辑器或学习如LaTex,Texinfo或Linux DocBook SGML等标记语言。 有些其他基本格式可能更适合于多种演示输出格式(如后记,Emacs信息),但在当今世界,简单的TEXT和生成的HTML希望满足所有需要。 Perl和Emacs也是跨平台的工具(Windows,Unix ..),并且易于安装,所以工作是希望没有障碍。 帮助维护此文档的工具包括(不需要!):

此文件的文本版本使用以下命令转换为HTML。 您需要Perl解释器5.4或更新才能调用t2html.pl脚本。 --Out选项在当前目录中生成文件pm-tips.html。 请熟悉GNU RCS ident(1),如果您有可用的话。 重要的是,您可以标记这些工具的有趣的文本,以便有人可以概述您提供的文件

      % per -S t2html.pl                                              \
--html-frame \
--title "Procmail tips page" \
--author "Jari Aalto" \
--meta-keywords "procmail, sendmail, mail, filter, FAQ, ube" \
--meta-description "Procmail tips page" \
--base http://pm-doc.sourceforge.net \
--document http://pm-doc.sourceforge.net \
--url http://pm-doc.sourceforge.net \
--html-body "LANG=en" \
--Out \
pm-tips.txt

1.5.1发送改进

因为我不是英语,我后悔文件中的任何打字错误。 如果您有任何时间,5-10分钟会发现一些拼写错误或误用英文动词,请继续向本页面的维护者发送补丁。 向本文档发送更正的首选方式是diff(1)输出。 以下是如何进行更正将其发送给他们。 diff选项-u仅在GNU diff中可用,请尽可能发送-u diff。 如果您没有-u选项,请使用-c选项:

      %   cp pm-tips.txt pm-tips.txt.orig

... load the pm-tips.txt to your text editor
... edit the file and save
... Generate the difference (a patch(1) compatible file)

% diff -bwu pm-tips.txt.orig pm-tips.txt > pm-tips.txt.patch

...Send content of pm-tips.txt.diff by mail to document maintainer.

1.6关于介绍Recipe

这里提供的Recipe是从网络和procmail档案收集的。 Recipe尽可能保持原样,但必要时可以概括一下这些想法。 如果某些Recipe不能公布,请a)向 [维护者]发送备注b)发送邮件到procmail邮件列表,并询问如何更正。 有时在正则表达式中使用了一个简单的点(。),在这种正则表达式中,正确的,迂回的方法将是使用转义的点。 如果你想要非常严格,你应该在适用的地方使用转义的点。

      # free hand version     # pedantic version
:0 :0
* match.this.site * match\.this\.site

Procmail也接受没有引号的作业,如下所示:

      var = value
num = 1
dir = /var/mail

但是在本文档中,采用了严格的风格,其中文字字符串分配了双引号:

      var = "value"

那是因为procmail代码检查器(Emacs package tinyprocmail.el )不会警告失踪的美元符号,这可能已被很好地忘记了。 Emacs包font-lock.el ,一个语法高亮助手,也显示双引号的字符串颜色。

      #   If you do this...

var = value

# then you might have made a typo. It is in fact not clear
# what was intended:

var = "value" # Did you mean: literal assignment?
var = $value # Did you mean: variable assignment?

配方标志也不会卡在一起,因为视觉区别:0和标志是一个有价值的。 推荐哪些旗帜保持在一起,并在后面详细说明哪个顺序。

      # Erm, all stuck]      # This may be visually more clear
:0ABDc: :0 A BD c:

1.7Recipe中使用的变量

这些是procmail模块 pm-javar.rc的一部分,并在配方中使用。

      #   Pure newline; typical usage if you want to write
# Something directly to procmail's active logfile:
#
# LOG = "$NL message $NL"

NL = "
"

有关详细信息,请参阅“改进Space-Tab综合征”部分

      WSPC    = "     "               # whitespace: space + tab

SPC = "[$WSPC]" # Regexp: space + tab
SPCL = "($SPC|$)" # whitespace + linefeed: spc/tab/nl
NSPC = "[^$WSPC]" # negation

s = $SPC # shortname: like perl -- \s
d = "[0-9]" # A digit -- Perl \d
w = "[0-9a-z_A-Z]" # A word -- Perl \w
W = "[^0-9a-z_A-Z]" # A word -- Perl \W
a = "[a-zA-Z]" # A word, only alphabetic chars

写作Recipe现在有点简单,至少对于习惯于阅读Perl正则表达式短名字的人来说,看起来更加清晰:

      :0
*$ Header-Name:$s+$d+$s+$d # Matches "Header: 11 12"
{
# Matched "whitespace" + "digit" + "whitespace" + "digit"
# Do something
}

SUPREME = 9876543210,是导致procmail保释的最高得分值。 [david]实际上最大值是2147483647,但是9876543210更容易记住/输入,并且也会起作用。

PMSRC = Procmail模块源代码目录。 * .rc文件所在的位置。 你想要的地方。 通常是$ HOME / pm或$ HOME / procmail / lib。 在这里您可以保留procmail文件,日志文件和includerc脚本。 另一个常用的同义词是PMDIR

SPOOL =您的procmail提供分类邮件的目录。 喜欢邮寄名单:

      list.procmail, list.lynx-users, list.emacs, list.elm

和工作邮件:

      work.announcements, work.lab, work.doc, work.customer

和你的私人讯息:

      mail.Usenet, mail.private, mail.default, mail.perl

和不重要的信息

      junk.daemon, junk.cron, junk.ube

如果您直接阅读procmail提供的文件,该目录通常是$ HOME / Mail或$ HOME / mail。 如果您使用其他读取这些文件作为邮件假脱机文件(如Emacs Gnus)的软件,则该目录通常为〜/ Mail / spool或类似的。

MYXLOOP =用于防止重新发送已经被处理的消息。 通常$ LOGNAME @ $ HOST ,但这可以是任何用户选择的字符串。 使其成为您的地址唯一。 在本文中,定义是:

      MYXLOOP = "X-Loop: $LOGNAME@$HOST"

SENDMAIL =发送撰写邮件的程序。 通常标准的Unix sendmail(1) ,但它必须有一些开关。 请参阅手册页了解更多信息。 我们在脚本中使用以下定义:

      SENDMAIL = "sendmail -oi -t"

NICE =在Unix环境中,可以使用nice(1)来降低调度优先级。 如果您意识到每个邮件启动的外部进程有多少,那么降低此类流程的优先级就会变得有礼貌。 您可以在本文档中看到外部进程在启用NICE时被调用:

      :0 w                # Same as "nice -10 script.pl"
| $NICE script.pl

IS功能; 测试文件或目录属性的功能。 例如IS_EXIST被定义为“test -e”等等。 IS功能的定义与系统有关。 例如在Irix上,“-e”选项不被识别,最近的等价物是“test -r”。 所有IS函数都在pm-javar.rc模块中定义。

1.8关于“无用的猫奖”

FIXME:替换wc -l并使用其他示例。

一位着名的Perl程序员和Perl书籍作家Randal Schwartz开始给“无用的猫命令”给予奖励,只要有人写了没有令牌“<”的例子。 喜欢这个:

      % cat file.name.this | wc -l

相反,他写道,调用应该是这样写的,它会保存管道(不要忘记wc可以直接读取文件,这是一个例子)。

      % wc -l < file.name.this

[Paul David Fardy pdf@morgan.ucs.mun.ca ]在管道中有重量,但真正的成本正在进行中。 尝试在/ etc / motd或此消息上运行100次。 我的测试表明,无用的猫双重实际和处理时间(实际,用户和系统时间大致加倍):

      $ cat > /tmp/randall <'EOF'
[[ -n $COUNT ]] || COUNT0
typeset -i i=1
while (( i < $COUNT )); do
< /etc/motd wc;
(( i = i + 1 ))
done > /dev/null
EOF

$ cat > /tmp/useless <'EOF'
[[ -n $COUNT ]] || COUNT=100
typeset -i i=1
while (( i < $COUNT )); do
cat /etc/motd | wc;
(( i = i + 1 ))
done > /dev/null
EOF

$ set -x
$ export COUNT0
$ time ksh /tmp/randall
$ time ksh /tmp/useless

这变得重要,例如,当您决定使用procmail过滤所有邮件 - 例如寻找病毒签名。 我可能会决定只看前3或4千字节。 这不是消息的大小 - 大多数都是小的 - 但是导致问题的消息的数量。 你想加倍我们邮件的处理成本吗? 我正在查看所有用户邮件的系统级过滤器。 我正在考虑Sendmail的邮件过滤器与procmail过滤。 我可能会使用两者。 而且考虑到所有的过滤器真的只是妨碍合法流量,如果我天真地加倍了成本,那么真的会让我失望。

2.0 Procmail指针

2.1 procmail在哪里开发

Philip Guenther guenther@gac.edu目前正在处理和协调procmail错误修复。 请将任何procmail错误发送到邮件列表或 bug@procmail.org 。 开发邮件列表正在procmail-dev@procmail.org上运行 SmarList 。 最新Procmail代码:

      http://www.procmail.org/
ftp://ftp.procmail.org/

手册页

      http://www.voicenet.com/~dfma/intro.html

2.2 Procmail资源

Procmail在Usenet新闻组comp.mail.misc中 讨论

Procmail档案
ftp://ftp.informatik.rwth-aachen.de:/pub/packages/procmail/从procmail邮件列表的文章:从1994-08到1995-05(A.gz文件:约2Meg,当未压缩)更多的文章可以在< http://mailman.rwth-aachen.de/pipermail/procmail/ >找到。 搜索页面位于http://www.rosat.mpe-garching.mpg.de/mailing-lists/procmail/

Nancy McGough nm@noadsplease.ii.com - Prcmail快速入门
http://www.ii.com/internet/robots/procmail/qs/
http://www.ii.com/internet/faqs/launchers/mail/filtering-faq/

Era的Procmail常见问题和链接集
http://www.iki.fi/~era/procmail

Timo Salmis教授的Procmail页面
http://www.uwasa.fi/~ts/info/proctips.html访问http://www.owasa.fi/~ts/info/spamfoil.html查看Timo的“使用电子邮件密码系统​​制造垃圾邮件”

Joe Gross的Procmail短篇教程
http://www.procmail.net/ jgross@stimpy.net ...使用procmail和ph的功能,您可以设置自己的邮件列表,而不需要在自己的机器上安装root。

Google的procmail指针
http://directory.google.com/Top/Computers/Software/Internet/Clients/Mail/Unix/Procmail/

Eli在Procmail
请参阅Eli Bearded的寻址技巧, 网址http://www.faqs.org/faqs/mail/addressing/

康科迪亚大学的procmail页面
http://alcor.concordia.ca/topics/email/auto/procmail/ ...人们经常会问如何避免收到“垃圾邮件”邮件,或者如何从恼人的邮件反弹邮件。 这些页面告诉你如何安装procmail; 然后,您可以定制它来做所有这些事情,或任何你想要的。 webdoc@alcor.concordia.ca

2.3 Emacs的Procmail模式

如果您使用Emacs,请参阅位于< http://tiny-tools.sourceforge.net/ >的Procmail编程模式 tinypm.el ,并可用于语法检查procmail配方。 以下是其输出示例:

      *** 1997-11-24 22:13 (pm.lint) 3.11pre7 tinypm.el 1.80
cd /users/jaalto/junk/
pm.lint:010: Warning, no right hand variable found. ([$`']
pm.lint:055: Pedantic, flag orer style is not standard `hW:'
pm.lint:060: Warning, message dropped to folder, you need lock.
pm.lint:062: Warning, recipe with "|" may need `w' flag.
pm.lint:073: Warning, Formail used but no `f' flag found.

2.4 Procmail模块库项目

2.4.1哪里可以得到各种模块

Procmail模块库
托管在sourceforge CVS服务器,并可供任何人参与。 访问< http://pm-lib.sourceforge.net/ >。 alan.stebbens@software.comalan.stebbens@openwave.com

2.4.2术语

subroutine =在INPUT中获得某些内容并以OUTPUT进行响应的一段代码。 子程序不是特定于消息。

Recipe =一些有些自包含的代码:它从消息中读取某些内容,或根据消息中的匹配进行某些操作。 Recipe可能是消息特定的。

2.4.3使用模块的前言

在模块列表中,一些模块是配方,一些可以被认为是子程序。 让我们来看一下讨论的地址exploder模块。 首先,可视化以下熟悉的编程语言伪代码:

(ret-val1,ret-val2 ...)=函数(arg1,arg2,arg3 ...)

函数可以返回多个参数,并且可以将多个参数传递给它。 清楚到目前为止 让我们来看看如何应用于procmail模块:

      RC_FUNCTION  = $PMSRC/pm-xxx.rc # name the subroutine/module
RC_FUNCTION2 = ...

INPUT = "value" # Set the arg1 for module
INCLUDERC = $RC_FUNCTION # Call Function( $arg1 )

:0 # Examine function ret val
* ERROR ?? yes
...

这也应该很清楚。 您只需要查看您打算使用的子例程/模块,才能在调用之前找出需要设置的参数(INPUT)。 文档还会告诉您返回哪些值,例如其中一个是ERROR。

如果它是Recipe/模块,呼叫将几乎相同,但是不是返回值,Recipe/模块最有可能对您的消息做某事或写入数据文件等。 配方/模块的级别高得多,因为它可能会调用多个子例程/模块。 子程序和配方模块类型之间的区别并不清楚,但是我希望以上内容可以说明Procmail模块/子程序/配方概念。

2.4.4头文件模块

这些类似于C中的#include .h文件,它们定义了常见的变量,但不包含实际的代码。

  • pm-javar.rc定义标准变量:SPC WSPC NSPC SPCL和perl样式\ s \ d \ D \ w \ W和\ a \ A(仅字母字符)
  • headers.rc - 从Alan的procmail-lib。 定义标准的正则表达式和宏:address,from,to,cc,list_precedence

2.4.5一般模块

  • pm-jafrom.rc - 不必要地调用formail导出FROM字段。 如果所有其他失败,请使用formail。
  • get-from.rc - 从Alan的procmail-lib。 得到“最好的”从地址。 设置FROM和友好,后者是“友好”的用户名sans地址。
  • pm-jaaddr.rc - 从INPUT中提取各种邮件组件的子例程。 像address = foo@some.com,net = com,account = foo ...
  • pm-jastore.rc - 一般邮箱传送的子程序。 将MBOX定义为放置消息的文件夹,该子程序将适当地存储它。 支持单个mbox,“.gz”mbox文件,目录文件和带有rcvstore的MH文件夹。

2.4.6低级日期和时间处理

对于这些,您可以从某个地方获取日期字符串,然后将其提供给其中的某些子例程:

  • pm-jatime.rc - 低级子程序。 从变量INPUT分析时间“hh:mm:ss”
  • pm-jadate1.rc - 低级子程序。 解析日期“Tue,31 Dec 1997 19:32:57”from variable INPUT
  • pm-jadate2.rc - 低级子程序。 从变量INPUT解析ISO标准日期“1997-11-01 19:32:57”
  • pm-jadate3.rc - 一个低级子程序。 解析日期Tue Nov 25 19:32:57来自变量INPUT
  • pm-jadate4.rc “调用sh​​ell命令”date“一次构造RFC”Tue,1997年12月31日19:32:57“,并解析YY MM HH和其他值。 你通常使用这个子程序,如果你不能得到其他地方的日期。

2.4.7高级日期和时间处理

您可以使用这些Recipe直接从邮件中获取日期:

  • pm-jadate.rc - 更高级的Recipe。 从邮件头读取日期:From_ Received,或者如果没有成功,调用shell 日期 。
  • date.rc - 更高级的配方。 从Alan的procmail-lib:解析日期或从标题Resent-Date :, Date和From

2.4.8转发和账户模块

  • pm-japop3.rc - 使用procmail实现的Pop3 movemail。 您可以发送一个“pop3”请求,将您的邮件从帐户X移动到帐户Y.每个邮件都是单独发送的。 此配方监听“pop3”请求。
  • pm-jafwd.rc - 远程控制转发。 您可以使用“控制消息”更改转发地址,或使用“控制消息”打开/关闭转发
  • pm-japing.rc “发送短信回复当主题包含单词”ping“显示帐户已启动,邮件地址有效。
  • correct-addr.rc - 从alan的procmail lib。 帮助将邮件从OLD地址转发到新地址,并做一些邮件列表邮件管理。 这个Recipe文件旨在使用户将邮件从旧地址转发到新地址变得容易,同时通过邮件通知CCI他们的记者来教育他们的记者。

2.4.9假期模块

  • pm-javac.rc - 您假期回复的框架。 该Recipe将处理休假缓存并撰写初始回复; 你只需要填写(就像把假期信息放在身上)
  • ackmail.rc - 从阿兰的procmail lib。 procmail rc确认邮件(带有假期消息或确认)

2.4.10基于Message-id的模块

  • pm-jadup.rc - 按Message-Id处理重复的邮件。 将重复邮件存储在单独的文件夹中。
  • dupcheck.rc - 从Alan的procmail-lib。 如果当前邮件具有“Message-Id:”标头,则通过“formail -D”运行邮件,导致重复邮件被删除。 可以在缓存中使用MD5哈希。

2.4.11 Cron模块

  • pm-jacron.rc - 您的日常cron任务的框架。 此配方包含所有必需的检查,以确保每当一天更改时调用includeserc。 (日变化受您收到的消息的影响)。 您自己的cron includerc每天运行一次。

2.4.12备份模块

  • pm-jabup.rc - 将消息保存到备份目录,并且每天只保留N条消息。 由Jari包装的John Gianni的想法。 注意:对于您收到的每条消息,实现将始终调用shell; 因此,如果您每天收到多条消息,建议不要使用此模块。 相反,使用cron模块每天只清除一次消息的备份目录,而不是每次消息到达时。

2.4.13确认模块

  • pm-jacookie.rc - 处理cookie(唯一ID)确认。 也称为Procmail认证服务(PAS)。 这个简单的procmail模块将只接收返回“cookie”键的用户的消息。 您可以使用它来保护您的邮件列表免受假的“订阅”消息或从不知名人士(通常是垃圾邮件发送者)发送邮件,这些垃圾邮件发送者不会将Cookie发送给您自己“验证”。 使用子程序pm-jacookie1.rc,它生成唯一的cookie; CRC 32默认。

2.4.14 Mime模块

  • pm-jamime.rc - 子程序读取MIME标题,并将mime版本,边界字符串,内容类型信息放入变量中。
  • pm-jamime-decode.rc - 在主体中解码quoted-printable或base64编码的配方。
  • pm-jamime-kill.rc - 附件杀戮配方:擦除额外的mime cruft,只留下纯文本。 杀毒应用程序:ms-tnef附件(MS Explorer 7k),HTML附件(Netscape,MS Express)vcard(Netscape),PCX附件(Lotus Notes)。
  • pm-jamime-save.rc - 保存简单文件附件的配方。 当您在邮件中收到一个文件附件时,该配方可将其保存在单独的目录中。 内容也被解码(base64,qp)同时保存。

2.4.15过滤邮件正文或标题

  • pm-jadaemon.rc - 通过更改主题来处理DAEMON消息以反映a)错误原因b)最初发送消息的人c)原始主题发送以及主题是什么。 将DAEMON消息存储到单独的文件夹。
  • pm-jasubject.rc “标准化主题”Re 32 :FW:Sv:message“或任何其他派生到事实上的”Re:message“
  • pm-janetmind.rc - Reformat http://minder.netmind.com/ messages,默认的4k消息被缩短为几行。

2.4.16杂项模块

  • pm-jaempty.rc - 检查邮件正文是否为空(无关)。 如果消息为空,则将变量BODY_EMPTY定义为“yes”或“no”。
  • pm-janslookup.rc - 在给定的地址上运行nslookup。 如果您使用“formail -rt -x To:”返回地址,则可以在发送回复之前验证域是否已注册。 使用已经查找的域的缓存。
  • guess-mua.rc - 猜测邮件用户代理并设置MUA:MH,PINE,MAIL

2.4.17邮件列表模块

  • pm-jalist.rc - 从邮件中提取邮件列表名称的子例程。 每次订阅新邮件列表时,是否需要在.procmailrc中添加新的配方? 如果你这样做,看看这个模块,它检查消息,并定义变量LIST来保存邮件列表名称。 您可以直接使用它自动保存消息到正确的文件夹。 没有更多的手工和手动存储邮件列表消息。

2.5 Procmail代码过滤UBE

Sysadms 记住 :垃圾邮件过滤在MTA中更有效率地完成,特别是如果您只是看着From和To行。 例如,您可以在Exim中设置阻止\ d。* @ aol \ .com(即以数字开头的任何aol.com本地零件)的规则。 AOL保证他们的地址都不以数字开头。 在收到消息之前,Exim在SMTP级别拒绝这样的虚假地址。

pm-jaube.rc - Procmail模块库的UBE过滤器
丹尼尔·史密斯(Daniel Smith)将垃圾邮件的配方发布到了procmail邮件列表之后,代码被采纳并被更广泛地处理了更多的UBE。 模块无需特殊设置,可通过简单的INCLUDERC进行安装。 没有使用其他ube列表文件,所有UBE检测都使用procmail规则进行。 该模块可在Procmail模块库中找到,网址为: http://pm-lib.sourceforge.net/

凯瑟琳·汉普顿的Spambouncer
http://www.spambouncer.org/ ...附件的procmailRecipe/过滤器,我称之为“垃圾邮件保护程序”,适用于对垃圾邮件(未经请求的垃圾邮件)生病的用户,并希望将其过滤掉邮件尽可能容易。 这些配方可以用作整个系统的共享配方,也可以由个人为自己的邮箱使用。

垃圾过滤器
http://www.pobox.com/~gsutter/junkfilter/http://sourceforge.net/projects/junkfilter ... Junkfilter是一个用户可配置的基于procmail的电子邮件过滤系统。 Recipe包括伪造标题,关键词,常见垃圾邮件域,中继服务器等等。

非夸张的浮标
http://www.cs.mu.OZ.AU/~amb/ ... Procmail包含弹出垃圾邮件的文件。 需要与普通用户的sendmail。

3.0干运行测试

什么是干运行测试?

这意味着您可以直接使用示例测试邮件来调用procmail测试脚本

      % procmail $HOME/pm/pm-test.rc < $HOME/tmp/test-mail.txt

脚本pm-test.rc具有您正在测试或改进的procmail配方。 test-mail.txt是包含头文件和正文的任何​​有效的邮件消息。 您可以使用任何文本编辑器,例如vi , pico , nano , emacs或xemacs 。 这是一个简单的测试邮件骨架。 逐字复制:

      From: me@here.com
To: me@here.com (self test)
X-info: I'm just testing

BODY OF MESSAGE SEPARATED BY EMPTY LINE
txt txt txt txt txt txt txt txt txt txt

请记住,您可以在干运行调用中定义环境变量。 这里有一个例子,procmail只是执行脚本,没有什么好奇。

      % procmail VERBOSE=on DEFAULT=/dev/null \
~/pm/pm-test.rc < ~/txt/test-mail.txt

假设脚本打印某些东西来记录文件,但是您可以将其全部转储为屏幕。 没问题,首先通过在shell提示符处调用tty来找出你的tty值,并在命令行上传递它。 这里默认的LOGFILE是针对重定向“LOG =”命令和语句:

      #  `tty' tells what to fill in /dev/..

% procmail VERBOSE=on DEFAULT=/dev/null \
LOGFILE=/dev/pts/0 \
~/pm/pm-test.rc < ~/txt/test-mail.txt

3.2为什么在干运行之后,From栏位不行?

为什么现在说“从foo @ bar Mon Sep 8 14:38:06 1997”?

别担心这个。 在生成任何自动回复后,通过formail运行消息是一个副作用 - “formail -rt”生成的自动回复没有“From”头(对于传出的消息是无意义的),所以第二个formail添加一个,不知道稍后会被sendmail忽略(sendmail会从中提取日期,但这是可忽略的)。 你只看到它,因为你保存到一个文件夹,而不是邮寄。

获取procmail变量的默认值

总是以这种方式来学习一个变量的初始值(注意强引号),Stephen用来在构建SmartList的脚本中获取$ SENDMAIL的procmail的值:

      procmail LOG='$PATH' DEFAULT=/dev/null /dev/null < /dev/null

由于LOGFILE尚未定义,因此$ PATH将被打印到屏幕上。 一个警告:如果在$ PATH的定义中有任何变量(如$ HOME),它们将在输出中扩展。

要记住的事情

获取最新的procmail

很多麻烦表面只因为你有一个旧的procmail版本。 一定要有最新的。 敲你的系统管理员或ISP,直到他安装这个版本,不要放弃,如果你认真使用procmail。 这是一个检查你的procmail版本号的命令:

      % procmail -v

4.2 Csh的波浪号不支持

真正的csh或Emacs的怪胎已经习惯于使用波浪号(〜)到处,但现在必须放弃这种习惯。 Procmail不支持它 只需使用 $ HOME 。 当你写procmailRecipe,认为不要 csh 。 这个设置将自动让你的大脑调整到正确的编程习惯。

一定要写正确的Recipe

Recipe开始于 :0或只是 :但后一种有点危险,容易错过。 小心写 0:因为它很容易发生。 在开始配方的冒号后总是放一个零。 在procmail的第一个版本中,您将放置条件数,默认值为1.这是令人讨厌的,计算机可以使计数更容易,所以斯蒂芬做了这样一个计数为0表示条件都是以 *开头的行。 默认值为1,除非给出 a , A , e或 E标志,否则默认值为零。 总是 开始一个 RECIPE with :0 。

4.4始终设置SHELL

如果您的登录shell是C shell(csh或tcsh),请避免使用havoc:作为预防措施,请始终将以下内容放在 $ HOME / .procmailrc的顶部。

      SHELL = /bin/sh

4.4.1如果系统没有/ bin / sh,你被迫使用csh / tcsh

[ kuhlmav@elec.canterbury.ac.nz ] Csh和tcsh首先执行.cshrc,那么如果,只有当它是登录shell(而不是子shell),它才执行.login,它应该包含基本的重要系统设置像stty命令。 同样,bash和ksh用户被教导在.profile中定义和导出PATH,所以我们的每个shell启动文件不会以.cshrc的方式破坏在.procmailrc中设置的PATH。

[philip] ...我被其他系统管理员告诉过,有一些系统在cshrc之前csh被黑客入侵.login。 由于种种原因,我怀疑这些是基于的系统
较旧版本的BSD(比如2.3 BSD)。

对于tcsh,.login和.cshrc来源的顺序是一个编译时选项,默认为.login之前的.cshrc(或.tcshrc)。 可能会有一些wackos在那里改变系统的内存默认值。 我建议电击作为适当的治疗方法。

...完成系统管理员在Crays,Convexes,Suns,SGI,Decs,运行BSDI,Linux和FreeBSD的PC,我从来没有遇到.cshrc在.login之后提供的系统。 如果有人去修改订单,我很想知道一个有效的理由。

4.4.2 Procmail将不能正常工作,SHELL设置为csh派生

[1998-08-17 PM-L kuhlmav@elec.canterbury.ac.nz Volker Kuhlmann] ...的责任在于procmail及其文档。 显然,procmail被编程,假设登录shell是sh派生的。 这个假设是a)不是很好,b)没有在其他非常好的文件中说明。 当然用户可以将SHELL设置为tcsh。 如果那么procmail太愚蠢了,它应该这么清楚,上面提到的使用tcsh的人的问题将从这个清单中消失。 一个也可以很好,并指出上述在procmail文档中提到的陷阱(3)。 通常在.login中配置终端配置。 如果它被转移到.cshrc它应该被正确包围if .. endif。 也许在bashrc中配置终端是不习惯的(哪里还有一个修辞问题),但是
没有理由在tcsh上责怪它。

我的.cshrc只有在登录shell(shell 1级)时才能设置环境。 procmail显然运行一个登录shell。 正如我前面所说,有没有很好的理由独立设置一个完整的PATH是否shell是交互式的。 所以,当procmail使用SHELL = tcsh执行程序时,PATH被设置为tcsh的默认值。 这可能是或可能不是可取的,这取决于个别情况。 没有问题,可以避免(用-f运行tcsh)。 如果它在procmail文档中很好。

但是,PATH变得不那么重要了(只有一个副作用,我没有意识到,直到2个人指出)。

4.5检查并设置PATH

很可能您的 $ HOME / .procmailrc看到的默认PATH环境变量不够。 为了安全起见,所以在.procmailrc中转义到shell时,可以找到所有需要的二进制文件,将 PATH变量设置为第一个语句。 添加另一个系统中不存在,但存在于另一个系统中的路径可以在多个服务器上使用相同的 $ HOME / .procmail (如HP,SUN,IBM,Linux)

      PATH = $HOME/bin:\
/usr/contrib/bin:\
/bin:/usr/bin:/usr/lib:/usr/ucb:/usr/sbin:\
/usr/local/bin:/opt/local/bin:\
/vol/bin:/vol/lib:/vol/local/bin:${PATH}

4.6始终保持登录状态

最好把这些变量放在你的.procmailrc的开头。 当您开始使用procmail时,您也希望知道所有发生的事情,以及为什么您的Recipe无法正常工作。 几乎所有问题的答案都可以在日志文件中找到。 由于日志文件将增长到相当大,请记住设置一个cron作业以保持中等大小。

      LOGFILE     = $PMSRC/pm.log
LOGABSTRACT = "all"
VERBOSE = "on"

4.7不要为目录添加尾部斜杠

删除尾部斜杠:如果您最终在Apollo的DomainOS上停止,那么双斜杠是网络引用。 如果目录具有尾部斜杠,它将在大多数操作系统上扼杀(他们将其视为“/。”)。

      DIR         = /full/path/to/www/directory/    # Wait...
FILE = $ARCHIVEDIR/file # Ouch !

4.8记住DELIVERED是什么意思

当procmail发送邮件时,无论是文件还是管道命令,如果写入成功,那么邮件被认为已经被传送,并且处理停止与该配方文件。 以下是手册页的相关文字:

...有两种Recipe:提供和不交付Recipe。 如果发现传送配方匹配,则procmail会认为邮件已被传递,并在成功执行配方的操作行后停止处理rcfile。 如果发现不传送配方匹配,则在执行此配方的操作行后,rcfile的处理将继续。

4.9小心在错误的地方发表评论

你喜欢评论很多,把它们贴在可能的地方吗? 是的,我也这样做,遇到麻烦,因为在procmail中没有任何评论代码。 请注意以下示例

      :0          # comment, nice tune...
* condition # OUCH, Ouch, ouch. This comment must not be here!!
# Hm, Old procmail versions don't understand this
# Are you sure you want to put comments inside
# Condition line?
* condition
{ # comment ok
# comment ok
:0 # comment ok
/dev/null # comment ok
} # comment ok

所以,要看的地方就是条件线。 后来的procmail版本可以理解这些,但如果你打算分享你的Recipe,玩安全,并考虑向后的可移植性。

4.10支撑位置

请注意您的大括号,并记住旧的procmail版本不像较新版本那样宽恕。 下面你会看到古典的“测试OK条件第一,如果失败,然后做别的事情”。 看到侧面的评论。

      :0
* condition
# No space allowed here!
{} # Wrong, at least _one_ empty space
:0 E
{do_something } # Again mistake, must have surrounding spaces

4.11本地锁文件用法

只有当procmail正在做一些应该被序列化的事情时,才需要锁定文件,也就是说,当一个进程一次只能执行一次时才需要这样做。

这通常意味着任何时候你写的文件,你应该有一个本地的锁,最好是根据写入的文件的名称。 转发操作('!')和99%的所有过滤器不需要锁定文件。 但是,如果筛选器在过滤时写入文件,则可能需要锁定。 当通过简单的文件操作将邮件写入文件时,Procmail总是执行内核锁定。 所以即使你忘记了锁定冒号,如果已经编译了内核锁,procmail试图玩安全。

小心放置锁定冒号(:)

       :0: a      # Ouch! Wrong unless you want a lock file named a
:0 a: # Okay.

请注意,在提供您手动编写内容的配方时,您必须使用具有> token的本地锁定文件,因为procmail无法自行确定锁定。 它只能从>>令牌确定锁定文件。 然而,把一个锁文件放在这样的Recipe当然是完全没用的。 所以你也可以完全省略锁定。

      #   Save last body of message to file mail.body

:0 b: mail.body$LOCKEXT
| cat > mail.body
  • 如果procmail rcfile中的命令行包含“>”,则本地锁定文件的名称将被隐式,而第二个冒号就足够了。
  • 如果命令不写入文件,或者不写入同一个文件(包括使procmail运行相同的命令的匹配的字母)可能同时运行,则本地锁定文件是不必要的。

也看这个。 不启动克隆的嵌套块不能在启动大括号的配方上占用本地锁定文件。 启动克隆的嵌套块可以。 (见错误)

      :0: file$LOCKEXT
{
# error: "procmail: Extraneous local lock file ignored"
# - This lock file will be ignored
# - If the recipes inside the braces try to use file.lck
# as a lock file, then you'll have a deadlock situation.

:0 :
/tmp/tmp.mbx
}

让我也解释为什么w这么重要。 请注意,这两个是相等的。 这里的W是隐含的。 注意 :这仅在打开嵌套块的配方中才是真实的。 在具有程序,转发或传递动作的Recipe上, W '与w不同 ,不同于两者。

      :0 c: file$LOCKEXT      :0 Wc: file$LOCKEXT
{ ... } { ... }

引用源代码中的评论,“尝试保护用户免受他的幸福无知”。 当涉及到锁定文件时,父母将始终等待克隆的小孩退出。 唯一的问题是它是否应该被记录。 如果想要克隆的孩子失败,那么你应该使用w标志,ala:

      :0 wc: file$LOCKEXT
{ ... }

本地锁文件可用于锁定克隆; 父亲procmail将在克隆退出时将其删除(因此它作为克隆的全局锁定文件)。 如果支持的块不启动克隆,则要求本地锁文件会生成错误。

4.12全局锁定文件

如果要在Recipe运行时阻止所有内容,即使在这种 情况下 ,请使用全局锁定。 例如在这个构造中,更新message-id缓存文件的formail必须用全局锁文件来保护。

      MID_CACHE_LEN   = 8192
MID_CACHE_FILE = $PMSRC/msgid.cache
MID_CACHE_LOCK = $PMSRC/msgid.cache$LOCKEXT

LOCKFILE = $MID_CACHE_LOCK

:0
* ^Message-ID:
* ? $FORMAIL -D $MID_CACHE_LEN $MID_CACHE_FILE
{
LOG = "dupecheck: discarded $MESSAGEID from $FROM $NL"

:0 # no lockfile !
$DUPLICATE_MBOX
}

LOCKFILE # kill variable

您不能使用本地lockfile如下所示:

      :0 : $MID_CACHE_FILE$LOCKEXT
* ^Message-ID:
* ? $FORMAIL -D $MID_CACHE_LEN $MID_CACHE_FILE

因为只有当条件匹配并且尝试了动作时,才会创建在标志行上命名的本地锁文件。

另外一个注意事项:仔细观察, 没有 :当传递到DUPLICATE_MBOX时锁定,因为外部全局锁定文件已经阻止所有其他procmail实例执行这部分配方。

4.13嗨,我在哪里把所有的! * $ ??

Ahem。 我不能告诉你究竟该怎么做,或者如何编写你自己的procmailRecipe,但我可以给你一个例子。 这是条件行令牌顺序的一种可能的样式:

      *$ ! ? BH VAR ?? test

除非你看到要比较的东西,否则这不会说太多。 这是一个完全有效的规则,但像上面的风格。

      :0
*$ ^Subject:.*$VAR
*! ^From:.*some
*B ! ?? match-the-string-in-body
*$? $IS_EXIST $FILE
*VARIABLE ?? set

在条件线上排列事情可能会更好。 第一列保留为美元符号,第二列为运算符等。 这里的关键是,我们可以看到,我是否可以在线上(最左侧)更改美元。

      :0
*$ ^Subject:.*$VAR
* ! ^From:.*some
* ! B ?? match-the-string-in-body
*$ ? $IS_EXIST $FILE
* VARIABLE ?? set
| | |
| | |
| | What is matched: (H)eader portion, (B)ody or (HB) both.
| | The (??) associative operator is required.
| |
| Not operator (!) or shell call (?)
|
Variable expansion (important)

4.14如果发送自动回复,请使用X-loop标题

不要发送自动回复而不检查“!^ FROM_DAEMON”条件,并且始终包含 X-Loop头并检查其存在以防止邮件循环

      :0
* conditions-for-auto-reply
*$ ! ^$MYXLOOP
* ! ^FROM_DAEMON
| $FORMAIL -A "$MYXLOOP" ...other-headers...

4.15避免额外的shell层和检查命令的SHELLMETAS

[dan]研究你的shell命令调用非常重要,并尝试保存额外的shell层的重载。 当您编写rcfile时,可能会额外工作一次,但可以节省每个邮件的时间。 当procmail看到SHELLMETAS的一个角色时,它会运行

      # Default SHELLMETAS: &|~;?*[
# Default $SHELLFLAGS: -c

% $SHELL $SHELLFLAGS "command -opts args"

代替

      % command -opts args

这是因为procmail调用其他程序的能力不包括文件名globbing([,*,?),背景(&),管道(|),继承(;)或条件继承(&&,||)。 如果它看到任何这些字符(在扩展变量之前),它将作业交给外壳。

有时候,这些角色出现在一个命令的参数中,而没有它们的shell元素意义,procmail真的可以在没有shell的情况下直接调用命令。 您可以在详细的日志文件中看到区别:如果procmail运行命令本身,它将记录

      Executing "command,-opts,args"

在每个位置参数之间使用逗号,但是如果它调用一个shell,那么rcfile中的原始间距在日志文件中不会变化:

      Executing "command -opts args"

所以,如果你知道你不需要shell扩展,可以用你的shell来打包:

      savedMetas  = $SHELLMETAS
SHELLMETAS # Kill variable

..command that does not need shell expansion features..

SHELLMETAS = $savedMetas

4.16想想你使用的shell命令

对于每个消息,procmail都会启动您在 $ HOME / .procmailrc中的进程 。 如果您以前没有注意过优化,现在是采取放大镜并检查每个配方和其中的流程的严重时间。 当你写你的私有shell脚本时,性能的影响不是那么重要,但是对于邮件传递,事情是完全不同的。 首先,我们来看一些程序和大小:以下是从一个Unix系统中,二进制文件包括调试和符号表代码。

      131072  /usr/bin/awk
196608 /usr/bin/sort
245760 /usr/bin/grep
262144 /usr/bin/sed
303552 /usr/local/bin/gawk
544768 /usr/contrib/bin/perl [perl 4.36]
822232 /opt/local/bin/perl

text data bss
awk: 72727 + 51316 + 15317 = 139360
sort: 173225 + 18496 + 183076 = 374797
sed: 237248 + 16992 + 56252 = 310492
grep: 221591 + 16176 + 53816 = 291583
perl4: 502220 + 36044 + 65632 = 603896
perl5: 633812 + 69612 + 2385 = 705809
gawk: 160018 + 5264 + 7168 = 172450

上面的二进制大小不是典型的情况:这些来自另一个系统

           4 Sep 28  /usr/local/bin/awk -> gawk
32768 Nov 16 /usr/bin/grep
49152 Nov 16 /usr/bin/sed
114688 Oct 20 /usr/local/contrib/gnu/bin/grep
155648 Nov 16 /usr/bin/awk
155648 Nov 16 /usr/bin/nawk
221184 Nov 16 /usr/bin/gawk
311296 Jan 27 /usr/local/bin/gawk
958464 Nov 2 /usr/local/contrib/bin/perl
1196032 Sep 14 /usr/local/bin/perl

Stan Ryckman stanr@sunspot.tiac.net希望你知道:

比较磁盘上的字节大小意味着什么都不在这里...这些东西可能或可能不会被剥离。 您看到的字节计数中包含的任何符号表都不会影响进程启动时间。 size命令可以更好地处理启动进程所需要的内容。 尽管如此,这三个细分可能都有自己的开销,这些细分对启动时间的相对贡献可能与系统有关。

嗯。 我们可以得出一些结论吗? 没有什么明确的,但至少是一些东西:

  • 在某些系统中, sed(1)和grep(1)可能大于awk(1) ,这是一个例外。 它们通常要小得多,使用得很快。
  • 复杂的命令将需要将许多进程链接在一起,如`grep -v | grep | 通常可以用一个awk(1)调用来完成sed。 问某个地方如何做到这一点awk(1)如果你不知道的语言,这是相当相似的perl(1)
  • 尝试使用标准的awk(1) 。 gawk(1)和nawk(1)较大,可能无法在所有系统上找到。
  • 不惜一切代价避免使用perl(1) (6)大于awk(1) 。 由于启动时的中间编译过程和内存容量大,Perl启动缓慢。
  • 请记住,如果procmail运行在一个专用的邮件主机上,它可能甚至没有安装任何好东西,只是无聊的标准版本; 这可能与当前主机上看到的不一样。

这里有一些更多的程序。 甚至没有想到用grep或awk提取字段,如“grep主题”,因为formail对于像这样的任务要小得多,更优化。 更好的是,很多时候,您可以使用procmail的正则表达式匹配来完成所有操作。

      37007 Sep  5 15:53 /usr/local/bin/formail   # 3.11pre7
28672 Jun 10 1996 /usr/bin/tr
20480 Jun 10 1996 /usr/bin/tail
20480 Jun 10 1996 /usr/bin/cat
20480 Sep 26 1996 /usr/bin/expr
16384 Jun 10 1996 /usr/bin/head
16384 Jun 10 1996 /usr/bin/cut
16384 Jun 10 1996 /usr/bin/date
16384 Jun 10 1996 /usr/bin/uniq
16384 Jun 10 1996 /usr/bin/wc
12288 Jun 10 1996 /usr/bin/echo

4.17调用shell程序时使用绝对路径

Shell程序员知道如果使用绝对路径来调用可执行文件,shell不必在$ PATH中搜索长列表的目录。 这可能会显着加速shell脚本。 使用这种优化的最佳方式是为这些程序定义变量。

你应该在你的procmail代码中使用这样的优化吗? 那是两个折叠的问题。 检查你使用多少个shell调用? 你使用grep或formail吗? 那么你可以优化这些电话。 为了便于携带,定义可执行文件的变量:

      #  perhaps defined in separate INCLUDERC
#
# INCLUDERC = $PMSRC/pm-mydefaults.rc

FORMAIL = /usr/local/bin/formail
GREP = /bin/grep
DATE = /bin/date

:0 fhw
| $FORMAIL -rt

当您将.procmailrc移植到具有不同路径的不同环境中时,您可以使用此配方以及上述之一:

      FORMAIL     = ...as above

:0
* HOST ?? second-host
{
# In this host the paths are different. Reset.

$FORMAIL = "formail"
$GREP = "grep"
$DATE = "date"
}

4.18暂时禁用Recipe

如果你有一个想要禁用一段时间的Recipe,有一个简单的方法。 在任何其他条件之前添加“false”条件行。 “”! 也很好地视觉上标示“这个Recipe不被使用”。

      #  This recipe stops at "!" and doesn't get past it.

:0
* !
* condition
* condition
{
...
}

4.19保留邮件备份,无论什么

在 .procmailrc中有一个安全措施是很好的。 虽然你是一个专家,已经检查过你的Recipe10次,但仍然有一些机会发生了一些事情。 一天早上,当您浏览 BIFF提醒日志时; 你注意到“嗯,有一个有趣的消息,但没有提交,它在哪里?” 当你去学习procmail日志(你一直保持日志一直在进行中),并且它触及你:“Gosh;我的脚本中的一个错误!消息被馈送到恶意管道,我已经把它标记在那里... “。 你非常遗憾的是,你没有首先备份信息。

所以,在你的procmail对你的消息做任何事情之前,把消息放到一些定期到期的文件夹中。 Emacs Gnus可以使邮箱过期,但也可以使用cron(1)进行清理。 之后,您可以放心,了解您的邮件是否安全。

      #   Your incoming messages are stored here, filtered by procmail

SPOOL = $HOME/Mail/spool

# Backup storage
#
# - This could be directory too. In that case you could use
# cron job to expire old messages at regular intervals
# - For once a day expiration, see procmail module list
# and pm-jacron.rc

BUP_SPOOL = $SPOOL/junk.bup.spool

:0 c:
$BUP_SPOOL

当然,您可以从备份过滤邮件列表消息,因为丢失一个或两个(100个)可能不是那么严重。 也许您可以使用两个备用线轴,一个用于邮寄列表,另一个用于您的非列表消息。

      :0 c:
* ! mailing-list1|mailing-list2
$BUP_SPOOL

如下所述设置日期变量,您还可以每天创建一个备份文件夹:

      $BUP_SPOOL    = $SPOOL/junk.bup.$YYYY-$MM-$DD.spool

这样可以轻松地删除早于指定天数的备份,手动或通过cron作业。

4.20 procmailRecipe的顺序

当你开始写很多procmailRecipe,你很快就会发现,重要的是你的Recipe的顺序是很重要的。 当每组Recipe开始增长太大时,将每个组移动到一个单独的includerc文件是很好的做法。 这是一个推荐的顺序,其中yur调用显示在邮件$ HOME / .procmailrc中
  • 备份重要消息
  • cron子程序
  • 处理重复的邮件
  • 处理DAEMON MESSAGES
  • 句柄加寻址消息(RFC加或sendmail加地址)
  • 处理服务器请求(文件服务器,ping响应...)

  • 删除邮件列表邮件
  • 发送可能的假期回复只有在所有以上
  • 应用杀戮文件
  • 检测mime并格式化或修改邮件正文
  • 保存私人讯息

  • 最后:FILTER UBE。

备份,cron和重复处理自然到您的.procmailrc的开头 。 接下来是一个灰色区域,Daemon加上处理和服务器消息。

邮件列表应尽可能早地处理,但在服务器消息之后,因为您希望首先处理您的服务。

在处理邮件列表之前,不要发送假期回复,以防止烦人的假期回复邮件列表。

之后,您将留下“已知”的私人消息和未知来源的消息。 对于快速垃圾邮件发送者的杀死文件(阻止基于发件人),在发送消息或每天发送数据之前,可能需要先检查其他消息。

最后但并非最不重要的是:将UBE检查器结束,以避免有效的邮件发生错误。 不要 发送 自动 投诉 返回 ,否则当自动回复者将投诉发送到有效来源时,您将得到灰白的头发。 你不想用“我的道歉,脚本有错误,不会发生aagin”的回覆。 所有有效的仇恨邮件,现在发给你。

将UBE删除到一个文件夹,手动选择需要操作的消息,并发送消息到接收链中的主管,解释他们的邮件转发被劫持。

5.0 Procmail标志

5.1标志的顺序

标志的顺序在实践中并不重要,但这里是一种风格的建议。 这里的想法是,最重要的标志放在左边,就像给 aAE优先级1, 立即影响Recipe。 优先级2被赋予标志 f ,它标示配方是否过滤某些东西。 另外(h)eader和(b)ody应该马上跟随 f ,这被认为是优先级3.在中间还有其他标志,最后一个标志是 c ,结束配方,或允许它继续。 另外根据 [david] :“...我确定把打开的冒号和 AaEe左边的 数字放在一起会导致错误。”

      :0 aAeE HBD fhb wWir c: LOCKFILE
| | | | |
| | | | (c)ontinue or (c)lone flag last.
| | | (w)ait and other flags
| | (f)ilter flag and to filter what: (h)ead or (b)ody
| (H)eader and (B)ody match, possibly case sensitive (D)
| Note: Procmail 3.22 bug
| <http://mailman.rwth-aachen.de/pipermail/procmail/2002-February/008355.html>
The `process' flags first. (A)nd or (E)lse recipe

你可以并排写标志

      :0Afhw:$MYLOCK$LOCKEXT

或者,如所建议的那样,将标志留在自己的socket中,以便更有特色地分开。 请注意,procmail变量$ LOCKEXT必须在$ MYLOCK旁边,因为它包含字符串“.lock”。

      :0 A fhw: $MYLOCK$LOCKEXT

5.2Recipe顶部的标志(警告)

[菲利普] 3.22版有一个错误,使'H'标志不被清除,这样一旦你使用它,它永远不会被清除。 因此,使用'H'标志将会导致仅使用'B'而不是'H'标志的后一种配方的问题。 无论哪种方式,您唯一应该使用“H”标志的是需要匹配头部和身体的配方。 如果你想要一个Recipe只匹配身体,而你正在使用3.22,使用“B ??” 修饰条件。 请参阅消息< http://mailman.rwth-aachen.de/pipermail/procmail/2002-February/008355.html >。 所以为了最有价值的可能,转换以前使用的所有条件行:

      :0 B
* body-check-here

使用这种格式:

      :0
* B ?? body-check-here

标记w和Recipe与|

[alan]如果过滤器程序退出0状态(0 == okay),那么procmail将用过滤器程序的输出替换原始输入体。 如果过滤程序退出除了零,procmail将向日志报告“错误”,并“恢复”输入(不过滤它)

[david]我非常确定, 只有在过滤配方中有w或W标志,情况才是这样。 没有w或W ,procmail不会关心过滤器的不良退出状态,并将用过滤器产生的任何标准输出替换过滤部分。 它可能仍然向日志报告错误,但它不会恢复以前的文本。 例如,这样会消灭一个消息的正文,即使没有我 :

      :0 fb
| false

然而,这样,procmail将恢复原来的身体:

      :0 fbW      # same results even if we add `i'
| false

[stephen]不,不是在所有的场合。 Procmail不会在这里关心退出代码。 但是,如果procmail检测到写入错误,它将恢复(因为缺少i标志)。 如果邮件足够长,并且不适合内核中的管道缓冲区(通常为10KB),Procmail将仅在这种情况下检测到写入错误。

5.4标记w,锁定文件和Recipe|

[手动]为了确保在管道完成之前锁定文件不被删除,您必须指定选项 w,否则一旦管道接受邮件,锁文件将被删除。 所以,如果你在Recipe中看到任何看起来像“>”或“>”的东西,那么应该立即响起你的钟声。 立即检查你是否包含了 w标志 锁定文件 : 。

      :0 hwc: headc$LOCKEXT
* !^FROM_MAILER
| uncompress headc.Z; cat >> headc; compress headc

5.5将f和w标记在一起

w告诉Procmail挂起,等待脚本完成。 嗯,你不觉得这个f旗已经被暗示了吗?

[david]当然, f标志足以使procmail等待过滤器完成,但是w意味着更多的东西:等待学习过滤命令的退出代码。 如果sed失败并出现语法错误,并且没有输出,没有W或w procmail将乐意接受null输出作为过滤器的结果,并且继续阅读现在的无体信息的配方。 另一方面, W或w sed将通过恢复未过滤的文本来响应非零退出代码。

5.6标志h和b

[david] hb是默认的; 只有当你不想要 b时,你才需要使用 h ,反之亦然。 你可以这么想: h意味着“失去身体”, b意味着“失去头”,但是两者一起取消了对方。

[philip] hb (供给整个消息)是动作的默认值。 如果您希望该操作仅适用于头部,则需要指定h 。 H是条件的默认值。 如果要针对整条消息测试条件,则需要指定HB或BH 。

5.7标记h并下沉到/ dev / null

当你把东西放到/ dev / null,使用 h标志,以便procmail不会不必要地尝试在那里提供整个消息。

      :0 h
* condition
/dev/null

[philip] Procmail知道它不应该在/ dev / null上创建一个本地锁,并且它不应该是内核锁定/ dev / null,它知道写“raw”(没有“从”转义或附加的换行符)。 这意味着procmail只需打开/ dev / null,用一个系统调用写入,并关闭它。 我不确定添加h标志是否会对现代UNIX内核产生真正的影响。 我想这取决于write()数据是如何优化的,特别是是否需要用户空间到内核空间副本,还是延迟。 如果它被延迟,则处理/ dev / null的代码可能不会这样做,并且写入的大小实际上并不重要。

5.8标志我和管标志f

国旗我在邮箱发货中是无用的。

[FAQ]以下内容将在某些时间工作,当信息足够短时,但这是巧合。 有了更长的消息,Unix开始注意发生了什么,因为它必须缓冲一些数据,然后当缓冲数据从不被读取时,会发生错误。 该错误传回给Procmail,Procmail尝试很好,并将您的原始邮件提交给这个恶意程序截断之前。 没关系,在这种情况下你想截断数据。 无论如何,修复很容易:只需添加一个:我标记为Recipe( :0fbwi而不是:0fbw ),使Procmail忽略错误。

      :0 fbw
* condition
| malicious-pipe

[dan]这里是为什么我需要标志(由Stephan提供):您告诉procmail过滤整个邮件(标题和正文),因此它会尝试将标题和正文写入过滤器。 然后procmail注意到不是整个身体被消耗。 Procmail在邮件传递时相当偏执,假定出现错误,并将其视为过滤器的故障。

      :0 fbwi
| head -2

5.9标记r

[philip] Procmail会自动打开 r (原始模式)标志,以将其传送到/ dev / null,因此您无需自行执行。

      :0 r        # you can leave out the `r'
* condition
/dev/null

[david]您可以在不想添加From_行的每个Recipe上使用r标志(原始模式)。 我假设没有一个已经在那里 r标志保持procmail确保顶部有一个From_行,底部有一个空行,但是如果procmail已经存在,它将不会删除它们。 另外,请注意在所有的formail调用中使用-f选项,以使formail不会添加一个From_行。

有人不需要From_线 - 我忘记了谁发现烦人的把r放在每个Recipe上,改变了源码,以防止procmail从来不添加From_行。 我认为一个更好的想法将是一个procmailrc布尔值来启用或禁用所有配方,而不影响其他用户。 (那么也许我们需要一个反向r标志来一次撤销一个Recipe的原始模式?)

5.10标记c的背景

...有趣。 我的c的想法是即使条件匹配,也可以考虑使用消息处理的CONTINUE。

[david]准确地说:当你有大括号时,思考“继续”而不是“复制”或“克隆”可以让你陷入困境。

早期版本的procmail,在大括号之前和克隆之前,在其文档中称为c标志“继续” 我认为在来源中仍然被称为。

当Stephen引入大括号(但不是在这一点上不克隆)时,当然这是隐含的,“{”的行为行是不传递的,而c是无关紧要的。 人们把c放在那里,因为他们希望procmail继续在一个比赛的大括号里面的Recipe,procmail用“无关紧要的c旗”警告。 没有伤害。

当斯蒂芬介绍克隆时,我很不高兴,他给了双重的责任,而不是为C引入一些新的东西,特别是因为绝对不需要克隆的人,而是希望大括号内的配方能够在同一个调用中运行因为一切都错误地把c放在大括号上,以确保procmail将“继续”。 人们会(并且确实)得到双重交付。

罗马Czyborra,虽然说,如果你考虑c代表“复制”,这涵盖c的两个用途:提供一个简单的Recipe的副本,或者如果有大括号,一个克隆procmail将处理内部的Recipe大括号 斯蒂芬同意并相应更改文件。

procmail的长时间用户和阅读旧文档的人可能仍然认为它是“继续”,但是从引入克隆来看,这不是一个很好的方法。 “复制”更安全。

5.11嵌套块之前的标志c叉子

[alan]嵌套块和 c标志的组合导致procmail为嵌套块分支子进程,而父跳过它并继续。 子进程不一定停止,除非 传递配方(没有 c标志)操作成功。

标记c并了解可能的分岔罚款

...我运行不需要序列化的shell命令,所以不是做标准的方式:

      :0 hic                  # nbr.1 / standard way
| command

我假设我可以通过使用这些来避免由(c)孤独的旗子引起的额外的叉子。 这两者有什么区别吗?

      :0                      # nbr.2 / alternative
* ? command
{ } # ...No-op, Procmail syntax requires this

dummy = `command` # nbr.3 / alternative

[philip]这里有一个误会。 让我澄清一下:

Procmail只能使用“c”标志在一个配方上分配一个完整的克隆,其操作是一个嵌套块。

如果它是一个简单的邮箱传递,管道或转发操作,那么procmail不会分叉“克隆”(对于管道和前向操作,procmail必须进行fork,但只能执行该操作)。 nbr.1和nbr.2采用相同数量的叉来执行。 他们也采取相同的有效写入数(如果你担心的话)。 后者还要求procmail等待命令完成。 nbr.3比上述两个更差,因为procmail不仅要等待命令完成,还可以将输出保存到命名变量中。

5.13嵌套块前的标志

给出以下配方,我们来检查标志部分

      :0 $FLAGS
{
do-something
}

[david] HB AaEe和D影响条件,因此在动作打开支架时有意义。 当然, HB和D将是无意义的,无论任何无条件的Recipe,但不应该导致错误信息。 通常,影响动作的标志在那里无效, bhfi和r总是,但其他则是部分异常:如果您使用c启动克隆,则w W和本地锁定文件可能是有意义的。 如果没有c ,则w W和本地锁定文件在支撑块的打开时无效。

5.14标志aAeE教程

[大卫] AaEe是相互排斥的,只有一个应该出现在一个单一的Recipe上。 [philip]其实这不是真的。 e不能与 E或(和procmail发出警告,如果你尝试), A是多余的,如果给出,但至少其中一些组合是有意义和工作。
  • A =尝试这个配方,如果条件成功的最新配方在该嵌套级别本身没有一个A也不是一个
  • a =与A相同,但是该操作必须在最新尝试的嵌套级别的配方中成功
  • e =几乎像A一样,如果条件匹配,但在最近尝试(未跳过)配方的动作失败,请尝试此配方。 宇宙与e相反。 e只是回想过去的ERecipe,因为他们的E被跳过了。 它不在乎以前的Recipe是否有A或标志。
  • E =如果在没有E的嵌套级别的最新配方上,条件失败,那么该级别的每个Recipe都确实有E ; 基本上与A相反

这些助记符可能有助于:

  • A:如果你在链的起点做了配方,可以尝试一下(A)
  • a:如果在该嵌套级别的最后一个操作是(a)完成)
  • e:如果最后一个动作在嵌套级别(e)rred
  • E: (E)lse因为到目前为止链条的情况并不匹配。 或者“尝试这个Recipe,除非最后尝试的Recipe匹配”。

      #   [philip] demonstrates `e'

:0 : # match, but action fails
/etc/hosts/foo


:0 A # no match
* -1^0
/dev/null

:0 e # this is skipped because the last tried recipe didn't match
{
...whatever
}

当我们连续使用时,它们之间的相互作用如何没有被我的知识完全测试。 考虑这个:

      :0
* conditions
non-delivering-action1

:0 a
action2

:0 e
action3

如果action2失败或action1失败(或者在这两种情况下),action3是否完成? [philip] Action 3仅在action2失败时才能完成。

如果答案是action2,如果action1失败,这是否可以让action3完成? 我认为这样做,但是如果第一个配方的条件不匹配,它也会运行action3? [philip]是的,是的。

      :0             #   [david]
* conditions
non-delivering action1

:0a
action2

:0E
action3

[philip]如果这不是你想要的,结合一些标志:

      :0
* conditions
non-delivering action1

:0 Ae
action3

:0 a
action2

如果条件匹配,则action1将被执行。 如果action1失败,则action3将被执行,否则action2将被执行[如果action1成功]

[david]我知道这个结构是什么,因为我使用它:

      :0
* conditions
non-delivering action1
:0A
action2

:0E
non-delivering action3
:0A
action 4

如果条件匹配,则执行action1和action2,并且action4不是(当然动作3也不是),即使action2是不传递的; 如果它们失败,则执行action3和action4。 第四个Recipe中的A指回到第三个而不是更远。 但我不知道这个:

      :0
* conditions
non-delivering action1
:0A
* more conditions
action2

:0E
non-delivering action3
:0A
action 4

现在,假设第一个配方的条件匹配,而第二个配方的条件不匹配。 会尝试第三个Recipe(因此第四个Recipe) 我会期待如此。 [philip]是的。 最后尝试的Recipe不匹配,因此E标志将被触发。

如果这不是你想要的,你可以这样做:

      :0
* conditions
{
:0
non-delivering-action1

:0
* more-conditions
action2
}

:0 E # ignores mismatch inside braces, looks only at same level
non-delivering action3

:0 A
action4

如果这是你想要的,你可以这样做:

      # if action2 is non-delivering or vulnerable to error that
# would cause fall-through

DID2 # Kill variable

:0
* conditions
non-delivering-action1

:0 A
action3

:0
* ! DID2 ?? (.)
non-delivering-action3

:0 A
action4

# if action2 is delivering and sure to succeed
:0
* conditions
non-delivering-action1

:0 A
* more-conditions
action2

:0
non-delivering-action3

:0 A
action4

[philip]或有兴趣的人,我会注意到a , A , e和E标志只有3种组合,不是非法或冗余的。 他们是Ae , aE和AE 。 我已经在Ae上面使用了。 以下是AE的示例:

      :0
* condition1
non-delivering action1

:0 A
* condition2
non-delivering action2

:0 AE
action3

action3只有在条件1匹配但条件2不匹配时才会执行。 没有A标志,如果任何一个失败,action3将被执行。 这也可以用一个而不是一个类似的结果来完成。

Procmail的“流量控制”标志可能并不容易直接描述(并且通过投放更多不同的交付和不交付配方的组合,这些都可能变得更加复杂),但是我发现它通常是做我期望做什么,如果没有或我有疑问,或者我想要特别清楚,我总是可以通过嵌套块明确地回退。 挑你的毒药

6.0匹配和正则表达式(正则表达式)

正则表达式抽象的哲学

这里有两种查看或写入regexps的方法。 弥补自己的想法。 有关正则表达式的更多信息,请参见< http://www.regexlib.com/ >。

赞成在Recipe中编写纯正反义词的人:

      [    ]<[    ]*("([^"\]|\\.)*"|[-!#-'*+/-9=?A-Z^-~]+)...  # "
  • 我不打算“维护”该代码,因为XXX的语法不会改变
  • 我以某种方式怀疑任何人都会更改这些正则表达式
  • 如果您的其他regexps中没有一个使用分类变量,并且您没有更改正则表达式,那么有什么意义呢? 可变的版本会更慢,并且会使用子进程来混乱环境。

有人立即想抽象的东西说(这是来自philip的伟大的Message-Id匹配配方)

      dq = '"'                                # (literal) double-quote
bw = "\\" # (literal) backwhack
atom = "[-!#-'*+/-9=?A-Z^-~]+"
word = "($atom|$dq([^$dq\]|$bw.)*$dq)'
local_part = "$word($s\.$s$word)*"

$s<$s$local_part... # ignore comment here

...抽象:当您将其分解为可管理的部分时,使代码更清晰,这些部分可能会表面可重复使用的部分。 它也使事情看起来更简单,甚至使新手能够理解那里发生了什么。 在我们没有连接到网络之后,其他人也可能会理解它。 所以,当然我们不能同意前面提到的保持正则表达式“纯纯格式”的参数。

  • 虽然你不会保持它,但这是其他人的榜样。 你先发布什么,人们会把它保存到他们的邮箱,并在网上的其他地方传播:“嘿,我救了这个,试试看”
  • 您可以编写隐秘的正则表达式或将其分解成整体看起来更简单的部分。 考虑新手的福利:-)这与“我一生中永不改变”毫无关系。
  • 附加变量的速度惩罚不是我们在实践中可以衡量的。 CPU甚至不会打嗝。 您的Recipe中额外的formail调用与100个变量一样昂贵10倍。 (我不知道如何测量,但启动一个shell并创建一个进程是一项更昂贵的任务)。
  • 混乱的env过程? 来吧 这也不重要。 没有外部进程使用小写环境变量名,否则它必须是真正的特殊程序。 所谓的“杂乱无章”的环境空间也是没问题的。 CPU甚至不会打嗝了。

6.2匹配不区分大小写

好吧好吧; 如果你阅读手册已经知道了。 但有时候有一些Unix经验丰富的人可能会认为procmail会像其他Unix工具一样区分大小写。 使用 D标志打开区分大小写。

6.3 Procmail使用多行匹配

Procmail默认使用多行匹配。 这意味着^和$匹配一个换行符,即使在正则表达式的中间。 现在你知道这一点,你可以很容易的将 $ [^>]解释为:一个换行符,后跟一行不是以a开头。

如果您在'\ /'匹配标记之后放置'$',那么如果有一个,那么procmail将包括匹配的换行符。 解? 除非你真的想要一个换行符,否则不要把一个美元符号,使用与所有换行符匹配的期间:

      :0
* B ?? ^Search-string: \/.+

6.4匹配之前展开标题

如果您有一个单独的行继续的标题,您不必担心换行符。 Procmail在匹配之前,将头部静默地展开到一行

      Received: from unknown (HELO Desktop01) (208.11.179.72) by
palm.bythehand.net with SMTP; 4 Dec 1997 23:29:09 -0000

:0 # note, match on continuation line
* ^Received:.*bythehand\.
{
# Do something
}

6.5改善空间Tab综合征

Procmail不了解 \ t和 \ n或[\ 0x00- \ 0x133]之类的标准转义码:

      #  Not what you think       # You have to write: space + tab
[ \t] [ ]

但是使用空格+标签不太可读,这是一个非常容易出错的结构。 以下是使用变量提高可读性的建议:

      WSPC   = "    "         # whitespace = space + tab
SPC = "[$WSPC]" # regexp whitespace, the short name
# SPC was chosen because you use this
# a lot in condition lines.
NSPC = "[^$WSPC]" # negation of whitespace

:0
*$ var ?? $NSPC
{
# match anything except space and tab
}

:0
*$ ! var ?? ($SPC|$)
{
# match anything ecxept space and tab and newline
}

但是您不能在括号内使用换行符。

      WSPCL  = "   "'         # Whitespace with line feed
'

# Won't work although WSPCL definition is correct.

*$ var ?? [$WSPCL]

而是使用变量语法:

      SPCNL = "($SPC|$)"      # space + tab + newline

如果您绝对需要一系列字符,请查看系统中是否有echo命令来定义这样的变量:

      NUL_CHAR        = `echo \\00`
DEL_CHAR = `echo \\0177`
REGEXP_NON_7BIT = "[^$NUL_CHAR-$DEL_CHAR]"

6.6处理感叹号

[philip]你需要第一个反斜杠,以保持procmail不考虑反斜杠作为反转匹配感的请求。 例如,这两个条件是等效的:

      * ! 200^1 foo
* 200^1 ! foo

因此,领先的'! 必须被反斜杠,包含在括号或括号中(我怀疑括号会更有效),或者以空的一对括号开头。 我会建议用以下这些之一写条件:

      * 200^1 \!!!!
* 200^1 ()!!!!
* 200^1 (!!!!)

6.7生成字符类的规则

在“字符类”(“[”和“]”之间的东西)中,元字符不需要转义。 那么反斜杠就是一个例外。 例如,[$ ^ \\将匹配任何一个文字字符美元,开口括号,插入符号和反斜杠。
  • 匹配“])”use [])]
  • 要匹配“[(”use [ ]
  • 包括文字^不能先是
  • 包括文字 - 必须是第一个,最后一个或\ -
  • 要包括文字\你必须使用\\
  • 包括文字]必须是第一个
  • 要包含一个文字[()或$只是在任何地方使用它

[elijah]如果你反转一个字符类“第一”表示就在(^)之后。 所以包含除了^和 - 之外的所有字符类必须如下所示:

      [^]^-]

[david]如果我想要文字$内括号如何? A $内括号,除非它开始一个变量名称,而$ $修饰符打开,总是指一个字面的美元符号。 它不能表示一个换行符,如果它出现在括号内。 保持免除“$”解释的一个好方法是将其放在括号中(除非还需要包括一个文字连字符,而不能先放置连字符;那么你需要逃避美元符号有一个反斜杠,最后放连字符,你可以选择脱离连字符,我猜),因为procmail知道“$”“不可能是一个变量的引用。

一般准则:

  • ($)总是匹配换行符,带或不带“$”解释;
  • [$]总是匹配一个美元符号,或用“$”解释;

6.8条件结束时匹配空间

[david]如果您需要在条件行末尾有标签或空格,可以使用以下命令:

      * rest of string .*
* rest of string[ ]
* (rest of string )
* rest of string ()
* rest of string( ) # This may be the best

[philip]从我看源码,最后两个应该在效率上是相等的,除了regcomp时间之间的跟踪差异,应该以与单个尾随空白相同的速度匹配。 字符类版本[]将会更慢。 当然,我怀疑你和你的系统管理员都不会注意到速度的差异,而且99%的系统都是I / O绑定而不是CPU限制,所以系统也不可能注意到。 我不能抱怨,因为我也去各种极端,寻求最后一点可能的表现。 好啊 第一个会慢一些,尽管也许不会比括号更慢。

6.9小心引导反斜杠

我想提出一个procmailRecipe,其中应该有条件“身体不包含特定的单词”。 这是我试过的:

      * ! B ?? \<word\>

[david]你已经陷入了领先的反斜杠问题,如果正则表达式的第一个字符是反斜杠,则procmail将其作为“引导空白的结尾”并将其删除。 你编码的意思是“一个小于符号,然后是这个词,然后是任何非字词。” (它也可以避免将小于符号作为大小运算符。)除非单词左侧的非字符字符小于符号,否则该正则表达式将失败(因此条件将通过) 。 尝试这个:

      * ! B ?? ()\<word\>

这也会工作:

      * ! B ?? \\<word\>

但是在休闲阅读中,它将看起来像“字面反斜杠,小于符号,单词,字边界字符”,所以我们在列表中通常推荐空的括号。

请注意,在procmail(它们必须匹配非字符字符)中的\ <和\>的含义与其在perl和egrep中的含义(它们分别匹配到零宽度转换为和逐字)不在这里玩耍 因为procmail的\ <和\>可以匹配换行符(真实的和假设的),所以很少是一个因素。 只有当单个角色必须同时作为一个单词的结束边界同时作为另一个单词的开始边界时,这是一个问题。 那么当你有一个作为\ /右边的最后一个字符时也是一个问题,但这很容易解决。

6.10正确使用TO宏

  • TO不是正常的正则表达式; 它是一个特殊的procmail表达式,旨在捕获任何目标规范。 有关详细信息,请参阅procmailrc(5)手册页的其他部分。
  • 喜欢TO_而不是TO,如果你有新的procmail。 TO_更好,因为TO过于松散
  • 请记住写下^ TO ,其中的锚点。
  • 不要在^ TO之间插入符号(^)和单词TO之间的空格。
  • 不要在^ TO和你匹配的文本之间放置一个空格; 它必须是^ TOtext如果这麻烦你,你可以使用TO()文本 ,以获得更好的文本分离。
  • TO中的两个字母都必须大写。

6.11 Procmail的正则表达式引擎

[philip] procmail的正则表达式引擎没有特殊的优化来锚定开始的行。 大多数具有这样优化的程序都有它因为其他原因需要线路区分(例如,默认情况下,grep打印包含匹配的整行)。 Procmail没有这样的其他原因,所以它像正则表达式中的任何其他普通字符一样处理换行符。 只要procmail可以说:“我看到的第一个字符必须是一个”foo“”,应该没有速度差异。 请注意,通过使一切都小写处理来处理不敏感情况,所以一封信首先不会引起角色类别或任何类似的Ghost。

>Recipe可能刚刚改变了头,procmail的大小
>不能保持一个字节计数指针,也不能保持一个行计数指针
>身体开始,但必须扫描头部找到
在开始身体搜索之前,颈部的空白线。

Procmail在读取头部时,而不是在搜索身体时执行此操作,因此无法避免成本。 让我重复一遍 搜索身体并不比搜索标题慢,如果我们忘记了这两个大小的最小影响。

6.12 Procmail和egrep差异

[大卫]
  • ^和$是非零宽度,并锚定到实际或推定的换行符(而不是一行的零宽度开始和结束);
  • 初始的^^或最后的^^分别锚定到开放或闭幕推定的换行符;
  • ^和$在一个procmailrc正则表达式的中间匹配一个嵌入的换行符(并且必须转义匹配一个插入符号或一个美元符号);
  • \ <和\>是非零宽度,并且匹配不会在一个单词(或一个真实的或推定的换行符)[而不是一个单词的零宽度转换]的字符; 它总是匹配一个非字词。 冒号后没有空格会失败。 这是病态,但仍完全符合RFC822。 因此,您应该使用(。* \ <)? 而不是仅仅。* \ <在结尾之后的结尾标题字段名称:

          ^Subject:.*\<humor\>        # Wrong
^Subject:(.*\<)?humor\> # Right, notice ?
  • *,?和+在没有\ /是吝啬而不是贪婪,而且一般都没有关系,但是在\存在\ /他们吝啬在\ /和贪婪右边的\ / ,而在大多数应用中,一行中最左边的通配符是从左到右的最贪婪和贪心。

6.13了解procmail的最小匹配(吝啬与贪婪)

...我想要一个procmailRecipe,将某些邮件保存到主题中指定文件夹名称(始终为一个数字)的文件夹。

      :0 :
* ^Subject: *\/[0-9]*
$HOME/Mail/$MATCH

[philip] ...这不会奏效。 对于具有标签后空格的主体,左侧的“*”将最小化(零次),然后右侧的内容将最大化匹配,但从静止开始,将什么也没有。 这是一个案例,procmail的最小匹配可能会引起巨大的混乱和沮丧。 解决方案通常如下:

      FORCE THE RIGHT HAND SIDE TO MATCH AT LEAST ONE CHARACTER

通过将配方更改为:

      :0 :
* ^Subject: *\/[0-9]+
$HOME/folders/$MATCH

它将工作,因为那时左手边必须匹配一直到第一个数字(但不是数字本身)。 如果你按照上限的规则,你几乎总是能够忽略procmail在这方面的奇怪。

[david]并检查procmail如何匹配“主题:关键词9999”

      * ^Subject:.*Keywords.*\/[0-9]*

procmail: Match on "^Subject:.*Keywords.*\/[0-9]*"
procmail: Matched ""

右边是可以贪婪的; 问题是我们似乎也期待在左边贪婪。 MATCH设置为null,与我们的预期相反。 这不是一个错误,而是一种经常被误解为提取广告的操作方式的误解。

记住只有右边是贪心的; 左侧是吝啬的,左侧的吝啬优先于右侧的贪婪。

提取以这种方式实现:整个表达式左右都被固定到最短的匹配; 那么分区标记被放置,右侧被重新分配到从分裂开始的最长可能的匹配。 棘手的部分是记住在吝啬阶段标记的部门。

如果表达式是

      ^Subject:.*Keywords.*\/[0-9]*

文字是

      <newline>Subject:<space>Keywords<space>9999<newline>

那么最短的可能匹配是全部的

      <newline>Subject:<space>Keywords

因为“。*”和“[0-9] *”都匹配为null。 然后,在“关键字”之后的空格处放置划分标记,并且procmail从该空间开始寻找与[0-9] *最长的匹配。 那又是null,所以MATCH设置为null。

我们看到,如果正则表达式更改为:

      ^Subject:.*Keywords.*\/[0-9]+

这是一个完整的蜡球。 现在最短的匹配是全部

      <newline>Subject:<space>Keywords<space>9

并且分割标记被放置在9.然后procmail从分割标记开始将最长的匹配反映到右侧,并设置MATCH = 9999。 不过这里

      ^Subject:.*Keywords\/.*[0-9]*

第二个“*”将不止于数字,而是通过它们到达行尾。 MATCH将包含所有匹配的“。*”加空匹配“[0-9] *”。

[好奇的读者]

给定线

      Subject: Keywords 9999

第二个(仅通过插入提取标记不同而不同)不匹配,不会设置$ MATCH:

      ^Subject: Keywords *9999        # matches ok
^Subject: Keywords *\/9999 # won't !

因为左侧将匹配“<newline>主题:关键字”和紧接着的文本“9999”,与右侧不匹配。 它实际上会使条件失败,并保持配方不执行。 它花费了大量的迂回编码,以便事先不知道数字前面有多少空格。

称它违反直觉,但它不是一个错误。 一般建议:始终确保右侧无法匹配null或左侧的最后一个元素不能与null匹配。 或者换句话说:强制\ /的右侧至少匹配一个字符。

6.14解释\ /和()\ /

MATCH将所有前导空白行放在3.11pre7中

[大卫] \ /左边没有任何东西意味着“一个预防”。 要使用提取操作符启动条件,请使用()\ /或\\ /; 后者看起来像直觉上像“反义词和文字前缀”一样(因为这意味着如果它在正则表达式中显得更远),所以我们大多数人更喜欢前者。

      *$ var ?? $s+\/$d+      # ok, \/ in the middle
*$ var ?? \/$d+ # Wrong, when \/ is at the beginning
*$ var ?? ()\/$d+ # No ok, () at the beginning

6.15解释^^和^

[philip] Procmail在匹配时不认为 线条 ; 但是将所有行连接在一起,然后运行正则表达式引擎。 这可能有点令人惊讶,但请考虑以下要丢弃任何可能是HTML广告的邮件

      #   Body consists entirely of HTML code
# something which'll match any message which has "<HTML>"
# in the body

:0 :
*$ B ?? $s*<HTML>
HTML.mbox

条件测试适用于整个身体。 如果你想限制它只匹配身体的开始,你必须说,所以使用^^标记,如你发现的。 一个简单的线锚(^或$)只是说,在匹配的文本中的特定点必须有一个换行符(或正在搜索的区域的开头或结尾)。 注意下面的领先锚点。

      #   trap spam where the *very* first line of the body started with
# <HTML>

:0 :
*$ B ?? ^^$s*<HTML>
HTML.mbox

究竟是什么“在搜索区域的开始处锚定表达式”,即^^?

[dan]技术上,一个开头^^锚定在procmail在搜索区域的第一个字符之前看到的假设的换行符(和一个关闭^^锚定到procmail在搜索区域结束之后看到的推定的换行符)。 当搜索区域为B时,这是相当于两个相邻换行符中第二个用于标记头部末尾的空行的点。

我提出的原因是这样的:如果头部和身体之间有多个空白或空白的行,^^将标记第二行的起始位置,而不是身体第一行的开头包含一些文字。

所以如果你想测试<pattern>是否是正文中的第一个打印文本,即使在第一行不一定是flush,你可能需要一个如下所示的条件,其中有空格/管道/制表符/ pipe / dollar。

      *$ B ?? ^^$SPCNL*<pattern>

6.16传统传统

呃,你已经知道了,如果你阅读手册页。 叠加条件行一个接一个地进行AND操作,其中所有条件必须存在:

      * condition1
* condition2

6.17 ORing传统

这里是简单的OR情况。 在某些情况下,这种风格是不可能的。 [philip]更多地了解这些情况。

      *  condition1|condition2

同样,两个退出代码测试通常可以这样进行OR操作

      * ? command1 || command2

但是有许多情况下,两个测试不能通过将它们组合成一个条件来进行OR操作:

  • 一个区域的正则表达式搜索与不同区域的正则表达式搜索进行OR
  • 正面正则表达式搜索[即,匹配到其模式] OR与负的正则表达式搜索[即,与其模式没有任何匹配]
  • 退出代码条件OR与正则表达式搜索条件
  • 退出代码条件寻求成功OR与退出代码条件寻求失败
  • 大小测试与其他任何东西(甚至另一个尺寸测试)

如何使所有使用SAME操作的OR条件? 我想要能够在某些请求上测试一些变体,全部在一个块中。

[hal]是的,这可以很容易地完成

      CASE = ""

:0
* case 1 tests
{
CASE = 1
}
:0 E
* case 2 tests
{
CASE = 2
}

:0
* ! CASE ?? ^^^^
{
# real work, perhaps with explicit tests on CASE
}

案例研究:从标题和正文查找文本

[david]除了编码OR的标准方式,还有一个特殊的方法来搜索给定单词的主题和主体:

      * HB ?? ^^(.+$)*(Subject:(.*[^a-z0-9])?|$(.*\<)*)remove\>

如果字符串不必在单词边框之前,它会变得简单一些:

      * HB ?? ^^(.+$)*(Subject:.*|$(.|$))*string

6.18 ORing和分数Recipe

一旦任何条件匹配,分数将获得正值,配方成功。 想法Erik Selke selke@tcimet.net

[时代评论] ...据称,评分系统会花费你比普通的旧正则表达式匹配。 浮点数学和所有这些,即使你使用非常简单的得分。 因此,要做到德摩根的方式可能会更有效率。

      * 1^0 condition1
* 1^0 condition2

我们现在可以用以前的成绩写出以前的病例stydy(HB ORing传统上)。 我很想这样写,当[大卫]告诉我以下。

      * 1^0 H ?? match-it
* 1^0 B ?? match-it

[david]这将工作,但它不是最好的方式做ORing,因为如果发现匹配的第一个条件procmail仍然需要测试第二个的麻烦。 更好的是,在每个条件下使用supremum得分:

      $SUPREME = 9876543210

*$ $SUPREME^0 first_condition_to_be_ORed
*$ $SUPREME^0 second_condition_to_be_ORed
* ... etc. ...
*$ $SUPREME^0 last_condition_to_be_ORed

达到最高分数后,procmail将跳过配方的所有剩余加权条件,并将其视为匹配项。 因为这个Recipe的所有条件都是加权的,所以一旦procmail找到一个匹配的条件,它将跳过其余的并执行该操作。

6.19 ORing通过使用De Morgan规则

[Tim Pickett tbp@cs.monash.edu.au ]我以为我会指出,有几种方法来做逻辑或条件。 有人在这里发布了一个涉及使用procmail评分系统的解决方案,但我认为您可以通过利用德摩根的规则进行评分:

      a or b      is same as   not(not a and not b)

或数学上:

      a || b <=> !( !a && !b )

这是一个做ORing的方法

      :0
* ! condition1
* ! condition2
{ } # official procmail no-op. MUST LEAVE SPACE
:0 E
action_on_condition1_or_condition2

7.0变量

7.1设置和取消设置变量

您已经使用“=”语法设置变量。 变量名区分大小写: var与 VAR不同

      VAR = /var/tmp  # directory
VAR = "this" # literal
VAR = 1
VAR = $FOO # another.
VAR = "$VAR at" # combined with previous value

取消设置变量是这样的

      VAR             # kill variable.
VAR= # same, but with old style
VAR = "" # Variable is said to be "null" now

您可以将多个作业放在同一行上,虽然不推荐:

      VAR=1  VAR=2  VAR=3

检查以下内容,这些都是等效的。 在没有任何SHELLMETAS的情况下,后面的勾号不需要shell,所以这些都不会产生一个shell

          #   case1: We Don't care if file exists this time...

VAR = `cat file`

# case2: The use of {} is considered "modern"

:0
* condition
{
VAR = `cat file`
}

# case3: oldish, and procmail specific and errors have
# been reported if you use this construct.
# Note: There must be no space in "VAR=|"

:0
* condition
VAR=| cat file

7.2变量初始化和sh语法

Procmail借用一些用于变量初始化的sh语法。 请注意,在procmail rcfile中,sh的$ {var:= default}和$ {var = defaultvalue}语法不可用。
  • VAR1 = $ {VAR2:-value}如果VAR2设置为非空值,则将VAR1设置为VAR2,否则将VAR1设置为默认值“value”
  • 如果VAR2置位,VAR1 = $ {VAR2-value}将VAR1设置为VAR2,否则将VAR1设置为默认值
  • VAR1 = $ {VAR2:+ value}将VAR1设置为“value”,如果VAR2为非空,则将VAR1设置为VAR2。
  • VAR1 = $ {VAR2 + value}如果VAR2置位,则将VAR1设置为“value”,否则将VAR1设置为VAR2。

这里是经典的使用示例

      VAR = ${VAR:-"yes"}     # set VAR to default value "yes"
VAR = ${VAR+"yes"} # If VAR contains value, set "yes"

有没有想过这是否在所有情况下都调用`date`?

      VAR = ${VAR:-`date`}

不,如果VAR已经有价值,procmail足够聪明地跳过呼叫日期 。 它不评估整个行。 下面你会看到每个初始化运算符。 仔细研究

      VAR = ""                # Define variable
VAR = ${VAR:-"value1"} # VAR = "value1"
VAR = ""
VAR = ${VAR-"value2"} # VAR = ""

VAR = ""
VAR = ${VAR:+"value3"} # VAR = ""
VAR = ""
VAR = ${VAR+"value4"} # VAR = "value4"

# Note these:
VAR = "val"
VAR = ${VAR:+"value3"} # VAR = "value3"
VAR = "val"
VAR = ${VAR+"value4"} # VAR = "value4"


VAR # kill the variable
VAR = ${VAR:-"value1"} # VAR = "value1"
VAR
VAR = ${VAR-"value2"} # VAR = "value2"

VAR
VAR = ${VAR:+"value3"} # nothing is assigned
VAR
VAR = ${VAR+"value4"} # nothing is assigned

如果要从多个初始值中进行选择,可以使用以下配方,而不是标准var = $ {var: - “value”}。

      :0
* VAR ?? ^^^^
{
# no value (or was empty), set default value here based on
# some guesses

VAR = "base-default"

:0
* condition
{
VAR = "another-default"
}

...more conditions..
}

您还可以在以前的Recipe中使用等效但可读性较差的条件:

      *$ ${VAR:+!}

它的作用是,因为如果变量包含一个值扩展为的值

       * !

哪里“!” 是procmail“假”操作。 另一种做同样的方法是,我们至少需要一个字符存在。 您可以使用regexp(。),这将需要至少一个字符存在,但您可能不喜欢匹配纯空间。

      * ! VAR ?? [a-z]

7.3测试变量

如果可能,执行积极测试,而不是否定,如下所示:

      * ! TEST_FLAG ?? yes

用负面测试,这将是:

      *  TEST_FLAG ?? no

使用诸如“是”和“否”之类的文字字符可能会更清楚,但是传统的“!” 否定考试 请注意,如果变量未设置或为空,则失败。

      * variable ?? (.)

这就是为什么会更好地测试:

      *$ variable ?? $NSPC

要么

      * variable ?? (.|$)

要求该变量包含至少一个字符。 但是,也不能检查变量是否设置,因为每个处理一个null变量与未设置的变量相同。 这是检查变量是否设置的最佳方法:

      *$ ! ${VAR+!}

[ gsutter@pobox.com ]这是另一种测试变量是否设置的方法,如果不是,请将其设置为默认值。

      :0
*$ ! VAR^0
{
VAR = "value"
}

7.4 $ VAR是什么意思?

[时代和大卫] Procmail 3.11,$ \ VAR将逃避正则表达式元字符。 它应该为Procmail自己的使用产生一个适当的反斜杠转义的表达式。 另外$ \ VAR将始终以前面的空括号开头。

您不能将$ \ VAR构造传递给shell程序,因为有一个前括号。 这是一个规范正则表达式的方法。 您可以将SAFE_REGEXP传递给像sed这样的外部程序。

      PROCMAIL_REGEXP = "$\VAR"

:0
* PROCMAIL_REGEXP ?? ^^\(\)\/.*
{
SAFE_REGEXP = "$MATCH"
}

[时代]请注意,这是稍微不正确的; Procmail会根据Procmail的需要反斜杠,而不是sed。 例如,Procmail不认为大括号是魔术(尽管在Procmail中也是很好的),而sed的许多现代变体都是这样的。

7.5使用变量时的常见缺陷

Procmail是挑剔的,原谅没有。 这里有一些最喜欢的错误:

      $EMAIL  = "foo@site.com"      # Done Perl lately? Remove that $

# Erm, this is ok, but many procmail recipe writers want to
# take extra precautions and include the regexps in parentheses.
# So, maybe (yabba|dabba|doo) would be more safe

REGEXP = "yabba|dabba|doo"

* Subject:.*$REGEXP # Hey, you need the "*$ Subject..."

*$ $REGEXP ?? hello # surely you meant '* REGEXP ?? hello'

7.6引用:使用单引号或双引号

注意这一点:

      VAR = "you"
NEW = 'hey "$VAR"' # won't extrapolate $VAR; you get literal
NEW = "hey '$VAR'" # extrapolates to: hey 'you'

甚至可以将单独的单词组合在一起

      VAR = "1 ""and"" 2" # same as "1 and 2"

不要让这些很多的报价打扰你,只要算出开始和结束的报价。 这里多余,但你可能需要一些类似的结构在别的地方。

      VAR = '1 '"'"'and'"'"' 2'  # same as: 1 'and' 2

[david]小心遗忘报价,就像你做的一样

      SENDMAILFLAGS = -oQ/var/mqueue.incoming -odq

Procmail翻译! 进入| “$ SENDMAIL”“$ SENDMAILFLAGS”作为procmailrc(5)手册页警告我们。 按照引用的规则,这意味着shell只看到第一个开关

      % sendmail -oQ/var/mqueue.incoming

我的建议:由于您需要$ SENDMAILFLAGS内的一个软空间,所以在定义$ SENDMAILFLAGS时使用引号,而不是使用! 运营商转发:

      SENDMAILFLAGS = "-oQ/var/mqueue.incoming -odq"

[Walter Haidinger walter.haidinger@gmx.net ]这是另一种方法:将procmail中的消息直接传递到所有用户家中的邮箱。 没有sendmail涉及,负载低得多。

      :0:
* <condition>
/var/spool/mail/someuser

[philip]假设“someuser”是密码文件中的一个实际用户(我没有关注这个线程,有些也许这不是真的),那么以下可能更好:

Walter Haidinger对此Recipe发表了评论:我很高兴地宣布,这项工作效果非常好。 对系统负载不再有任何伤害。 终于解脱了!

      :0 w
* conditions
|procmail -d someuser

这让procmail非常棘手的“screenmailbox()”程序以安全的方式处理虚假邮箱。

是否像转发一样安全? 传递给/ var / spool / mail / someuser的另一个sendmail使用相同的锁定机制,并注意到邮箱已被锁定? 我不想冒着破坏邮箱的风险。

[philip] Sendmail只能通过别名传递文件直接发送文件:

          whatever: /some/local/file

一般情况下,sendmail会调用本地邮件程序将邮件实际存储在一个文件中,因为这是procmail(对吗?),不应该有问题。 此外,sendmail 8直接发送内核级锁定。

7.7引用:将值传递给外部程序

当您将变量值发送到shell程序时,请记住要包含双引号。 下面你看到一个错误,因为SUBJECT的内容没有被引用,因此不能从perl变量 $ ARGV [1]获得 。

      :0                          # Use procmail match feature
* ^Subject:\/.*
{
SUBJECT = "$MATCH"
}

:0
* condition
| perl-script $SUBJECT # mistake; use "$SUBJECT"

还有另一种方法。 如果您的脚本可以访问环境变量(几乎所有程序都可以),那么您不需要在命令行上传递变量。 以上,SUBJECT已经在环境中,在Perl中可以使用:

      $SUBJECT = $ENV{SUBJECT};

接下来,你知道这两种Recipe有什么区别吗?

      :0
| "command arg1 arg2 arg3"

:0
| command "arg1" "arg2" "arg3"

你猜到了。 第一个引用整个命令,不做正确的事情,后者是正确的,并且取决于argN变量的内容。 无论如何,玩安全,总是添加引号。

有时候,您需要一些棘手的引用来获得单引号。 要注意这一点,因为这可能是您的grep命令似乎没有像你所期望的那样成功的原因。

      #  If $GREP "$arg" doesn't seem to work

* ? $GREP "'"$arg"'" $DATABASE

7.8从外部程序传递值

外部程序无法直接设置procmail变量。 程序必须将值写入外部文件,然后从这些文件中读取值。 仅捕获一个值很容易:

      var = `command`      # capture STDOUT

但是,如果一个程序修改了身体,并且导出了一些状态信息,那就更加棘手。 我们在这里假设脚本由您控制,并且已添加了switch -export-status选项,该选项使程序将信息打印到单独的文件。

      LOCKFILE    = $HOME/.run$LOCKEXT  # protect external file writing
valueFile = $HOME/tmp/values

# modify body, and export status values to external file: one
# value in every line
#
# VALUE1
# VALUE2
# VALUE3

:0 fb
| $NICE script.pl --export-status $valueFile

values = `cat $valueFile`

# Derive values from each line

:0 # line 1
*$ values ?? ^^\/[^$NL]+
{
var1 = $MATCH
}

:0 # line 2
*$ values ?? ^^.*$\/[^$NL]+
{
var2 = $MATCH
}

:0 # line 3
*$ values ?? ^^.*$.*$\/[^$NL]+
{
var3 = $MATCH
}

LOCKFILE # Release lock

[richard]或者从您的rc或外部程序中写入值文件

      PARAM1="value for param 1"
PARAM2="value for param 2"
PARAM3="value for param 3"

并阅读

      INCLUDERC $valueFile

现在没有必要担心读取与行的同步,或者关于添加新的参数,因为每个都被标记在valueFile中。

7.9将变量增加一个值N

[dan,phil和Richard]这是一个增加变量值N的方法。如果$ VAR不是一个数字,我们会收到一个错误。 请注意,如果$ VAR + $ N不大于0,则如果赋值发生在大括号内,则该配方将不会更改VAR的值。 您必须在关闭大括号后放置作业。

      :0
*$ $VAR ^0
*$ $N ^0
{ } # procmail no-op
VAR = $=

7.10比较值

调用shell的 测试函数做[-lt | -eq | -gt]太贵了,因为你可以使用procmail做同样的事情。 如果SCORE <= MAXIMUM,运行下面的do-something。 Recipe简单地从MAXIMUM中减去SCORE,并确定结果是否为正。

      :0
*$ -$SCORE ^0
*$ $MAXIMUM ^0
{
.. do-something
}

[时代的想法]如果它在MIN和MAX之间变得有点麻烦:

      :0
*$ $SCORE ^0
*$ -$MIN ^0
{
dummy # no-op, just for the LOG

:0
*$ -$SCORE ^0
*$ $MAX ^0
{
suitable
}
}

例如。 当值为MIN = 1时,MAX = 5,SCORE = 4

      procmail: Assigning "SCORE=4"
procmail: Score: 4 4 ""
procmail: Score: -1 3 ""
procmail: Assigning "dummy"
procmail: Score: -4 -4 ""
procmail: Score: 5 1 ""
procmail: Assigning "suitable"

7.11字符串:给定字符串中有多少个字符?

      :0
* 1^1 VAR ?? .
{ }
LENGTH = $

7.12字符串:如何删除尾随的换行符。

假设你使用了正则表达式,它在 MATCH中留下换行符($)。 如果你想知道为什么配方工作,提醒自己regexp操作符“。” 从不匹配换行符。

      :0
* VAR ?? ^^\/.+
{
VAR = $MATCH
}

7.13字符串:导出字符串的最后N个字符。

      #   1998-06-23 PM-L [walter] Note the use of
# the $ sign below to anchor to end-of-string...
#
# For last 2 characters use * VAR ?? ()\/..$
# For last 5 characters use * VAR ?? ()\/.....$

:0 # Last character
* VAR ?? ()\/.$
{
TAIL = $MATCH
}

7.14字符串:从字符串获取部分匹配。

[dan]使用procmail的 匹配操作符可以很容易地获得一个匹配。

      VAR = "1234567890"

:0
* VAR ?? ()\/3.*
{
result = $MATCH # now 34567890
}

但是从最后删除2个字符几乎是不可能的,而不需要外部处理。 最便宜的可能是expr ,因为它不需要shell来管道echo (因为sed会和我相信perl会):

      #   by resetting the shellmetas, this will only call
# `expr'. If we wouldn't have fiddled with shellmetas,
# this would have called two processes: sh + expr

saved = $SHELLMETAS
SHELLMETAS
result = `expr "$VAR" : '\(.*\)..'` # now 12345678
SHELLMETAS = $saved

ksh或bash也可以做到这一点:

      #   semicolon to force invoking a shell, actually
# first question mark will force a shell already.

saved = $SHELL
SHELL = /bins/sh
result = `echo ${VAR%??} ;`
SHELL = $saved

现在,如果你知道最后两个字符将是“90”,那就是不一样。 当然,如果第三个到最后一个字符是9,这完全拧紧。

      :0
* VAR ?? ()\/.*[^0]
* MATCH ?? ()\/.*[^9]
{
result = $MATCH # now 12345678
}

[jari]评论:如果必须使用shell,那么awk是简单字符串操作的好工具。 它的启动时间更快,perl的开销是由于内部编译。 awk也比perl消耗更少的资源。 以下将仅在VAR是连续字符串的字符串时才起作用。 (可使用ARGV 1

      saved       =   $SHELLMETAS
SHELLMETAS

VAR = ` awk 'BEGIN{ v = ARGV[1]; \
print substr(v,1,length(v)-2); exit }' \
"$VAR" \
`

SHELLMETAS = $saved

这个版本需要一些文件,任何文件,这样我们才能开始awk。 在前面的代码中,所有的工作都是在BEGIN块中完成的,没有文件被打开。

      saved       =   $SHELLMETAS
SHELLMETAS

VAR = ` awk '{print substr(v,1,length(v)-2); exit }' \
v="$VAR" /etc/passwd \
`

SHELLMETAS = $saved

awk:对于procmail来说, expr肯定是一个比awk更小的二进制文件,而且它需要更少的命令行代码来完成这项工作。 还要注意的是,还有一个是SHELLMETAS,以避免shell,因为awk代码包含括号; 因此它并不代替全部。

如果字符串由相同的分隔符分隔,还可以通过procmail手段从字符串的末尾删除单词。 让我们使用这个mail-list-request这个词,我们想缩短这个邮件列表。 [david]在PM-L中介绍了Recipe1998-06-16。

      VAR = "this-mailing-list"

# 1) if there is match at the end ending to these words
# 2) Get everything up till last match and store it to MATCH
# 3) Read MATCH, but exclude last dash "-"

:0
* VAR ?? -(owner|request|help)^^
* VAR ?? ^^\/.*-
* MATCH ?? ^^\/.*[^-]
{
VAR = $MATCH
}

7.15字符串:Procmail字符串操作示例

[1998-06-23 PM-L walter] ...现在我们应用这些公式来剥离字符串的最后一个字符。 特殊情况下有点丑陋。 我故意选择了最坏的情况。

      VAR         = "Testing 012301230111"
RC_APPEND = $PMSRC/pm-myappend.rc

:0
* VAR ?? ()\/.$
{
TAIL = $MATCH # last character of VAR "1"

# Get the longest match that does not end in the TAIL character

:0
*$ VAR ?? ()\/.*[^$TAIL]
{
HEAD = $MATCH # now "Testing 012301230"

# if the last two or more characters in VAR are
# identical, they all get chopped, oops

:0
* -1^0
* 1^1 VAR ?? (.)
* -1^1 HEAD ?? (.)
{
dummy = "tooshort"
INCLUDERC = $RC_APPEND
}
}
}

result = $HEAD # "Testing 01230123011"

# ........................................ pm-myappend.rc
# LENGTH(HEAD) plus 1 SHOULD equal LENGTH(VAR). That is
# not the case when the last 2 (or more) ending
# characters are identical. in that case, call appendrc
# recursively to stick back an appropriate number of
# TAIL characters.

:0
* -1^0
* 1^1 VAR ?? (.)
* -1^1 HEAD ?? (.)
{
HEAD = "$HEAD$TAIL"
INCLUDERC = $RC_APPEND
}

7.16如果邮件已提交,如何提起标志

      FILED = !       # ! is procmail "false"

:0 c: # We process the message more
* condition
foo

:0 a
{
FILED # Kill variable
}

...

:0 # Stop if previous cases filed the message
*$ $FILED
{
HOST = "_done_"
}

或者,如果procmail将邮件传递到邮箱,则会自动设置LASTFOLDER 。

      LASTFOLDER      # kill variable

:0 c:
* condition
foo

:0 c:
* condition
bar

... et cetera ...

:0
* ! LASTFOLDER ?? ^^^^ # Or ${LASTFOLDER+!}!
{
HOST = "_done_" # Force procmail to stop
}

7.17美元在条件线上登录。

#todo,检查这个Recipe

      This doesn't seem to work for me...

* ^TO()$\foo@bar.com

[david]以后的一个未转义的美元符号代表一个换行符,所以你在那里搜索以下内容:

  1. 与^ TO令牌的扩展匹配的表达式(其定义为锚定到行的开头),其次是
  2. 一个换行符,随后在下一行的开始
  3. “foo @ bar”[反斜杠转义f,不需要转义],后跟
  4. 任何不是换行符的字符(期间未转义),最后
  5. “com”。

改为:

      *$ ^TO()$\foo@bar\.com

#todo:在​​上述两个#todo中,美元似乎完全相同#todo示例:你确定这是正确的吗?

事实上,为了避免与foo@bar.community.edu的匹配,你可能想这样做:

      *$ ^TO()$\foo@bar\.com\>

7.18寻找神秘的foo变量

我有我的同事的procmail代码,他使用一个变量FOO,我在他的代码中找不到任何地方。 它也不是一个shell变量,因为它是文字的。 它从何而来?

您的procmail启动时运行/ etc / procmailrc,请检查。 它可以为所有用户定义一些常用变量。

7.19将代码存储到变量

在procmail配方中运行复杂代码的一种方法是首先将其存储在变量中。 想法 [时代] 。 您也可以在单独的shell脚本中执行此操作。 以下示例从邮件正文中读取URL:URL已经放在单独的行中,一些特殊的Subject用于触发HTML页面的转储:

      #   Code by [era]
#
COMMAND='while read url; do
case "$url" in
*://*)
lynx -traversal -realm -crawl -number_links "$url" |
$SENDMAIL $LOGNAME
;;
esac
done'


# Notice the trailing semicolon after `eval' !
:0 bw
* ^Subject: xxxxx
| eval "$COMMAND" ;

如果你想在嵌套块中运行代码,那么仔细看一下,在后面的勾号中有两个引号。 如果您留下双引号,SH_CMD中的每个单词将被单独解释:

      $SH_CMD = '$echo "$VAR" >> $HOME/test.tmp'

:0
* condition
{
# condition satisfied; run the given shell command
# and do something more.

dummy = `"$SH_CMD"`

..rest of the code..
}

类似的结构也适用于消息回显:

      MESSAGE='Thank you so much for your message.
Unfortunately, the volume of mail I receive .... (blah blah blah).
If your matter is urgent, try calling +358-50-524-0965.
'

:0 hw
* ! ^X-Loop: moo$
| ($FORMAIL -rt -A "$MYXLOOP"; echo "$MESSAGE") | $SENDMAIL

7.20将标题变成一个变量。

[david]以下是将整个标题变成一个变量的几种方法:

      HEADER = `$FORMAIL -X ""` # The space after the X is vital.
HEADER = `sed /^$/q` # also writable as HEADER=`sed /./!q`

:0 h
HEADER=|cat -

将整个标头保存为一个变量。 但它必须小于$ BUFSIZE。 这样做也可以,并且不需要外部进程:

      :0
* ^^\/(.+$)*$
{
HEADER = $MATCH
}

7.21将值转换为小写

如果你知道一个单词属于一组选择,你可以在procmail里面进行

      LIST = ":word1:word2:word3:word4"   # Colon to separate words
WORD = "WORD1"

:0
*$ LIST ?? :\/$WORD
{
WORD = $MATCH
}

但是,如果事先不知道这个词或字符串,那么这是一般的方式: [时代和大卫的想法]

      :0 D
* WORD ?? [A-Z]
{
WORD = `echo "$MATCH" | tr A-Z a-z`
}

8.0建议和杂项

8.1加快procmail

  • 使用绝对路径来承担从shell沿路径搜索二进制的负担:使用$ FORMAIL变量抽象。

          $FORMAIL = "/usr/local/bin/formail"

:0 fhw
| $FORMAIL -I "X-My-Header: value"
  • 如果\ n转义被支持,则扩展多行的多个回传命令可以转换为单回波命令。 你通常在自动回复中看到这些

          echo "........."; \
echo "........."; \
echo ".........";

-->

echo ".........\n" \
".........\n" \
".........\n";
  • 您可以通过将结果缓存在.procmailrc顶部来避免多个可能的昂贵的FROM_DAEMON测试。 你现在可以使用变量$ from_daemon,就像大哥FROM_DAEMON一样。 同样的想法可以应用于FROM_MAILER正则表达式。 如果你有pm-javar.rc ,它已经定义了变量$ from_daemon和from_mailer ,就像这样:

          from_daemon = "!"

:0
* ^FROM_DAEMON
{
from_daemon = "!!" # double !! means "OK"
}

:0
*$ ! $from_daemon
{
..do-it..
}

  • 计数后面的ticks,你知道procmail有多少shell调用必须启动。 看看是否可以最小化它们,并使用一些procmail代码。
  • ^ TO和其他宏是昂贵的,看看是否可以使用简单的标题:。* \ <match-it \>来代替。 那么这不是很清楚,这是否给你带来了很多速度的优势。
  • 每次需要头值时,不要调用“$ FORMAIL -xHeader:”,只要使用匹配运算符\ /就可以了。
  • 如果您在路上添加了多个标题,则可以将调用最小化为只有一个formail :请参阅本文档中的formail使用提示
  • 搜索身体是昂贵的,因为它包含更多的文本。 没有什么可做的,因为你需要使用B,无论如何,当你需要它。
  • 看看是否可以将某些任务移动到.cron文件。 procmailrc不是为了这些目的。 而不是每次在procmail中计算每日值,而是在04:00或21:00进行。 如果可以的话,不要在午夜运行cron,因为所有人都在同一时间运行crons。 如果可以使用“逻辑”日期更改时间(当您上班,离开工作时),请在cron工作中使用。
  • [philip]将LINEBUF永久设置为一个大的值可以减慢procmail的速度。
  • 删除所有调用perl并使用更好的系统的程序(如果你只是调用命令行perl,可能有一个等同的替代与awk tr sed 切 )
  • 检查每个shell命令,看看你是否需要SHELLMETAS。 如果可以将SHELLMETAS设置为空,则可以为每次调用外部命令调用“sh”。

8.2参见procmail安装示例

你还记得看看procmail附带的例子吗? 如果没有,现在是给他们一个机会来教育你的时候了。 这是一个可以看的目录。 如果您找不到要查看的目录,请从您的系统管理员处询问。

      % ls /usr/local/lib/procmail-3.11pre7/examples/

或者如果你真的很想自己去做,那就试试看。 目录/ opt / local用于HP-UX 10计算机,而forward包含如何为procmail定义.forward的示例。

      % find /opt/local/ -name "forward" -print

如果找到成功并找到文件,那么你知道procmail文件安装目录在哪里。

8.3打印收到的邮件的统计信息

如果保持procmail日志处理,它将记录消息被归档到哪个文件夹。 有程序 mailstat可以处理procmail.log文件并打印出不错的摘要。 如果您在午夜生成摘要并清除日志,则每天/每个文件夹的流量分析会变得非常漂亮。

      # -m merges all error messages into a single line

% mailstat -km procmail.log

8.4将UBE邮箱存储在配额外

我想将垃圾邮件存储在磁盘空间之外。 问题:如果我告诉procmail传递给,例如/tmp/spam.box,这样做很好(根据日志)。 不幸的是,它传递到/ tmp在邮件主机,我无法访问。 当为接收邮件调用procmail时,spam.box不会显示在shell机器的/ tmp目录中。

[philip]在这种情况下,在最可能的sendmail配置下,在shell机器上无法通过sendmail调用procmail:sendmail可能设置为将所有邮件转发到指定的邮件传递机器。

还有其他选项:您可以将邮件临时存储在您的帐户中,然后在shell计算机上重新处理邮件中的cron作业。 这可能比将每个消息触发到shell机器的rsh更有效。 如果你实际上得到足够的垃圾邮件,那就是推动你的配额,那么rsh太贵了 - 使用一个cron工作来调用这样的东西:

      cd your-maildir     &&
lockfile spam.lock &&
test -s spam &&
{
cat spam >> /tmp/spam.box && rm -f spam spam.lock || \
rm -f spam.lock;
}

警告:以上假设如下:

  • mail-mail / spam中的所有内容都是垃圾邮件,属于/tmp/spam.box
  • 不需要进一步过滤消息:它们只需要移动(它实际上将您的maildir / spam中的所有内容视为单个消息,并将procmail用作可靠的复制命令,因此使用/ dev的DEFAULT分配/ null为空procmailrc)
  • /tmp/spam.box不是一个目录

如果后两个条件不正确或如果他们可以更改,那么您应该使用formail -s将消息分开,并单独调用procmail。

[era]由于种种原因,许多站点都是跨挂载目录。 / tmp始终是本地的,但是/ var / tmp可能在登录主机和邮件主机之间交叉安装; 另一个尝试是/ scratch - 如果所有其他都失败,请要求您的管理员为此设置一个NFS共享。

8.5从消息中使用前5-30行

[时代]正则表达式抓住几行(或所有这些,如果不到五十)不会很漂亮,但它可以节省启动额外的进程。

      :0
*$ B ?? ^^$SPCNL*\/$NSPC.*$(.*$)?(.*$)?
{
toplines = $MATCH
}

消息开头的空白跳过当然不是必需的。 如果你抓住很多行,你可能会把 LINEBUF设置得很高, 比如 30:80 * 30 = 2400字节; 可能设置为8192或16384是一个好主意,取决于你想要匹配多少。 上面的人很快就很难,所以

      #  But if N=30, sed ${N}q if you don't have head

:0 i
{
toplines = `head -$N`
}

:0 a
* toplines ?? pattern
{
...do-it
}

8.6在脚本中使用cat或echo?

我看到很多使用'echo'的例子,

      :0
* condition
| echo "first line of message" \
"second ..." \
"et cetera"

我从“ariel”的spam.rc开始,让我习惯了

      :0
* condition
| cat file_containing_message

虽然我注意到spam.rc确实有一个配方使用echo方法。 选择每种方法的原因是什么?

这是一个比较表。 选择你认为最适合你的

  • Echos不具有对外部文件的依赖:所有内容都包含在.procmailrc文件中。 Echos将所有相关内容保存在一个文件中。 猫使您保持多个文件。 这是我倾向于echo的主要原因; 您可能在几台机器上有帐户。 在它们之间复制一个通用的.procmailrc是比较容易的,而不必复制一堆消息。 大多数情况下,两种方法之间没有任何区别。
  • echo更易于使用变量。
  • echo启动许多进程,只能启动一个进程,但是并不总是这样:在大多数当前的Bourne shell实现中,echo是一个内置的。 这也适用于tcsh。
  • 使用猫看到的主要问题是“当您忘记文件或摧毁文件时会发生什么?” 至少,我建议测试该文件是可读的,然后再对其进行测试。
  • [richard]反对回应的论据是它的标准化程度不高,同一台机器上可能存在不同的版本。 有些人认为-n,有些不会; 有的认识嵌入式元字符,有些不是打印的 。 然而,打印并不是所有系统上的一个内置的。 内置的注释与shell产生的情况有关。 当procmail直接处理调用时,它将始终寻找一个独立的可执行文件。 我猜,echo可能会更好,只要我们知道内置版本和独立版本之间的行为有任何差异。

8.7如何运行额外的shell命令作为副作用?

[jari]我曾经想知道什么是最明智的方式向我的日常“biff”日志文件发送关于我的.procmailrc执行过程中发生的事件的消息。 这就是我对[David]的看法

      # case 1: print to BiffLog

dummy = `echo "message: $FROM $SUBJECT" >> $biff`

[david]目标文件没有锁定的问题,除非将其放在大括号内,否则必须无条件地在每个消息上运行它。 (此外,procmail尝试将整个消息提供给一个不会读取的命令,但是补救措施并没有太大帮助。)

      # case 2: We consume delivering recipe and therefor have to use
# `c' flag.

:0 whic:
| echo "message: $FROM $SUBJECT" >> $biff

这里它锁定目标文件,您可以添加条件,所以它可能是最好的。 如果头部或身体小于一个缓冲区,则可以使用h或b限制不必要的写入数据,但我认为在大多数操作系统中,部分缓冲区和完整缓冲区数量都相同。

      # case 3: We use side effect of "?" here. Cool, but this
# doesn't do $biff file locking thus message order may
# not be what you expect.

:0
* condition
* ? echo message: $FROM $SUBJECT >> $biff
{ } # procmail no-op

我们有条件可能,但目标文件上没有锁定。 我会用方法2或其变体:

      :0 hic:                 #   we don't necessarily need `w'
* condition
| echo message: $FROM $SUBJECT >> $biff


:0 hi: # Or you could use this
* condition
dummy=| echo message: $FROM $SUBJECT >> $biff

[jari]现在,当[david]解释了各种各样的方式是如何不同的时候,我给出了我使用情况3的配方。当我向一个文件夹发消息时,我想发送一个消息给我的biff日志太。 想法是,下降条件已经匹配,然后我们使用“?”的副作用运行额外的命令。 令牌 就Recipe而言,“?” 是不做的 妄想的方式是将LOCKFILE添加到Recipe中,但可以想像这样的50种类似的Recipe...而且您了解为什么LOCKFILE被遗漏了。 只有担心连续写入biff文件时才需要。

      :0 :
* drop-condition
* ? echo message: $FROM $SUBJECT >> $biff
$MBOX

8.8从shell脚本强制“ok”返回状态

...“?” 技巧只允许运行一些额外的shell命令( true命令始终成功),而上述条件已经确定将发生下降。 如果一个行为不端的shell脚本总是返回一个失败的退出代码,你总能使条件成功。

      * ? misbehaving-shell-script || true

[david]如果脚本总是返回失败代码,只需执行以下操作:

*! 不正常的shell脚本

更复杂的情况是脚本可以返回成功或失败,但您不在乎哪个; 如果下降条件通过,则要运行操作行。 如果进程缺少写入stdout的权限或机会, echo也可能会失败。 更可靠的选择是真实的(1); 它的生活目的是做任何事情,但退出状态0。

命令:是一个内置的shell,它始终返回true状态。 不完全比true更可读(1)“||:”将保存true的调用(除非true被内置到$ SHELL),但是procmail仍然会运行一个shell。 另一方面,只要命令本身没有来自SHELLMETAS的字符 ,1 ^ 1的权重和任何“|| any ”都将避免shell进程。

然而,还有一个更好的方法来确保脚本的失败不会使procmail中止配方:

      :0 flags
* other conditions
* 1^1 ? shell-script
action

不管脚本的退出状态如何,条件将为1,并且不会妨碍procmail对配方操作行的决定。 加权退出代码条件类似于此(参见procmailsc(5)手册页):

      * w^x ? command

成功的成绩或失败的x。

      * w^x ! ? command

得分与此相同:

      * w^x  pattern_that_appears_in_the_search_area_$?_times

8.9让自己的.procmailrc可供他人使用

从来没有太多的了解procmail,最好的来源是人们完成的rc文件。 记住在您的procmailrc文件发布之前,请先给出您的procmailrc文件。 下面是一个
根据要求发送.procmailrc的配方。 如果你想发送更多的一个或两个文件(很多时候你想要放置其他文件),那么请不要使用这个代码,而是一般的文件服务器模块。

      :0
* ! ^Subject:.Re:
* ^Subject:.*send.*procmailrc
* ! ^FROM_DAEMON
{
:0 fhw:
| $FORMAIL -rt \
-A "Precedence: junk" \
-I "Subject: Requested .procmailrc"; \
-I "$MYXLOOP"

:0 a hwic
| ( cat - $HOME/.procmailrc ) | $SENDMAIL

:0 # trash the "Send procmailrc" request
/dev/null
}

8.10有效使用日期

注意 :请参阅模块列表,您将在其中找到日期和时间解析模块。 如果您的系统每次都相同,您也可以从第一个Received或From_头解析日期。 如果收到很多邮件,那将会更快的数量级,并减少系统负载。

在你的procmail脚本中多次调用日期不是一个好主意。 尽可能使用MATCH在procmail中有效,如下所述,我们只将日期调用一次。 如果您与服务器不在同一时区,并且您想要准确的日期报告,则可以将调用修改为以下内容:

      date = `TZ="KDT9:30KST10:00,64/5:00,303/20:00";date "+%Y %m %d"`

这里的基本配方

      # By [richard] add %H:%M%S if you want these as well

:0
* date ?? ^^()\/....
{
YYYY = $MATCH
}

:0
* date ?? ^^..\/..
{
YY = $MATCH
}

:0
* date ?? ^^.....\/..
{
MM = $MATCH
}

:0
* date ?? ()\/..^^
{
DD = $MATCH
}

TODAY = "$YYYY-$MM-$DD" # ISO std date: like 1997-12-01

8.11保持简单的头文件

这是一个简单的策略:记录所有进入的内容,并记录该消息发生的所有事情。 查看 BIFF文件夹中不断记录的简短信息。 您现在可以每天检查 BIFF日志,查看邮件是否正确地 放置到正确的文件夹中:请记住将 BIFF规则添加到每个配方,以便在收到邮件标题后记录接收器消息 [sunk-athere]

我在我的Emacs窗口中使用这个单行日志,该窗口通过实时模式进程一直更新(稍后再参阅Emacs工具部分)。 它给出了我收到的邮件的一个很好的概述:这是我的biff(1)等效于Emacs。

      # this requires that HH and MM have been setup before,
# see pm-jadate.rc

NOW = "$HH:$MM" # the time only
TODAY = "$YY-$MM-$DD $NOW" # ISO 8601: date and time

$NULL = $SPOOL/junk.null.spool # /dev/null is dangerous
BIFF = $PMSRC/pm-biff.log

# or if you prefer a log per day (easy for cleanup):
# BIFF = $PMSRC/pm-biff.log.$YYYY$MM$DD

# .............................................. headers ...

# DON'T USE THESE: they call shell
#
# FROM = `$FORMAIL -zxFrom:`
# SUBJECT = `$FORMAIL -zxSubject:`

:0 # Use procmail match feature
* ^From:\/.*
{
FROM = "$MATCH"
}

:0 # Use procmail match feature
* ^Subject:\/.*
{
SUBJECT = "$MATCH"
}

# ............................................. incoming ...
# record log of incoming mail

# or if you use a biff file per day, you could have:
# echo "$NOW $FROM $SUBJ" >> $BIFF

:0 hwic:
| echo "$TODAY $FROM $SUBJ" >> $BIFF

# ......................................... null recipe ...
# Now, this is how you add the "message" what happened
# to that mail. See "?" shell call in the recipe

:0 :
* From:.*(remove|delete|free|friend@)
* ? echo " [null-AddrReject]" >> $BIFF
$NULL

8.12 Gzipping消息

[Sean B. Straw PSE-L@mail.professional.org ]在通常将其折叠到文件夹中的Recipe传送线上,而不是:

      :0 c:
|gzip -9fc >> $MAILDIR/mail.mbox.gz

这将压缩每个消息,因为它进来(而且大多数是TEXT,它是一个很好的工作 - MIME,OTOH是邮寄一个人的最好的方法之一,因为它不能很好的压缩 - 但通过邮件列表的间接轰炸不要这样做),通常会大大减少所需的磁盘空间。 完成与.procmailrc结尾的以下内容,您可以拥有一个头文件,您可以通过查找有效的消息来添加到procmail配方,然后运行:

      gzip -d -c mail.mbox.gz | formail -s procmail -m recipe.rc

(请注意,如果配方在任何情况下传递到mail.mbox.gz文件,那么在运行此过程之前,您应该看看移动该文件,并使用移动的版本。实际上,这将是一个好主意,因为在您执行此操作时,新发送的邮件可能会显示在gzip文件的末尾 - 由于您的最终目标是能够消除垃圾邮件,因此您需要知道,在处理gzip压缩的邮件文件之后,可以删除它,而不会意外地打击新邮件)。

      :0
* LASTFOLDER ?? ^^^^
{
# Save the message in case we need to retrieve it.

:0 c:
|gzip -9fc >> $MAILDIR/mail.mbox.gz

# copy headers for easy browsing - including being able to
# identify lists you're being subscribed to.

:0 h:
header.log
}

8.13 .procmailrc的紧急停止

[jari]如果我在测试新Recipe时遇到不幸,它可能会循环运行,并且可能会不断向我发送邮件。 然后我必须快速回忆.procmailrc,然后开始禁用我个人的“控制”配方文件。 但是,我认为,在这样的情况下,每秒都是重要的,必须有一个更好的方法。 [alan]这已经很容易了 把它放在你的procmailrc的顶部:

      #   instead of leading dot file, you may prefer
# stopFile = $HOME/procmailrc.stop which shows up in default ls.
# In the other hand you can do ls ~/.procmail* to see both...

stopFile = $HOME/.procmailrc.stop

:0
*$ $IS_EXIST $stopFile
{
EXITCODE = $EX_TEMPFAIL # Means: retry later; requeue
HOST = "_stopped_by_external_request_"
}

然后,当测试您的procmailrc和灾难发生时,您可以简单地执行以下操作来禁用您的procmailrc过滤。

      % touch $HOME/.procmailrc.stop

[理查德]这也是包含INCLUDERC的候选Recipe。 结合这两个想法,我们有一个文件procmailrc.stop,其中包含Recipe,并附在.procmailrc顶部附近,当您不想要它时,请将它编辑到procmailrc.go。 Procmail抱怨丢失INCLUDERC,但是如果它们存在并且是空的,它不会抱怨它们。 另一个原因,不要使用虚线文件名,而是使用cp而不是mv。

9.0得分

9.1以分数为例

首先进行所有需要匹配,并设置 SCORE值。 在计算最终值后检查分数。 条件线说:
  • 从一些阈值开始:-250。
  • 将主题读入MATCH
  • 为每场比赛添加50! 注意“^ 1”:如果它读为“^ 0”,那么“!!!!”中只添加一个50,现在计算为4 x 50 = 200。请参见procmailsc(1)“^ N”语法。
  • 任何美元符号可能是垃圾邮件。
  • 找到不感兴趣的主题词
  • 而回覆的负数。
  • 通常垃圾邮件似乎没有Re:在主题字段。 (但不要依赖这个,垃圾邮件发送者已经开始使用“re:”)
  • 字母如!!! 经常在体内发现的垃圾邮件通常是指示。 为每场比赛添加100。

      # Idea by 26 Sep 97 Stephane Bortzmeyer <EM>[email protected]</EM>

:0
* -250 ^0
* ^Subject:\/.+$
* 50 ^1 MATCH ?? [!]
* 50 ^1 MATCH ?? [$]
* 100 ^1 MATCH ?? ()\<(free|sex|opportunity|money|great)\>
* -250 ^0 ^Subject: *(Fwd|Fw|re):
* B ?? 100 ^0 ()!!!
{ } # official procmail no-op

SCORE = $= # Score has been calculated

:0 fhw
| $FORMAIL -i "X-Spam-Score: scored $SCORE"


:0: # If score had positive value, sink message
*$ $SCORE^0
junk.spam.mbox

给出以下主题:

      "Great opportunity for free sex; no money required!!!!"

procmail以这种方式得分:! 被发现4次(200 /重量50),“free | sex ...”regexp匹配4次(400 /重量100)。

               condition score    Total sum so far
---- ----------------
procmail: Score: -250 -250 ""
procmail: Score: 200 -50 "[!]"
procmail: Score: 0 -50 "[$]"
procmail: Score: 400 350 "^Subject:.*\<free|sex|...
>"
procmail: Score: 0 350 "^Subject: *(Fwd|Fw|re):"
procmail: Score: 0 350 ! ""
procmail: Assigning "SCORE=350"

[david]关于可能的regexps及其区别的一些注释:

      * 100^1 ^Subject:.*\<(free|sex|opportunity|money|great)\>

这个条件说,对于包含这五个词中的任何一个的每个主题行来说,得分为100,而不是为主题中的每一个单词得分100,而对于包含任何这些单词的每个主题行,都为100。 所以除非有多个主题行,否则绝对不会超过100。 你看,它提供了五种替代正则表达式:

      ^Subject:.*\<free\>
^Subject:.*\<sex\>
^Subject:.*\<opportunity\>
^Subject:.*\<money\>
^Subject:.*\<great\>

Offhand,我认为下面的regexp将为“主题。*免费”和100为“性别”等级为400:100。当然,如果标题中的其他行包括字符串“性别”,“机会” ,“金钱”或“伟大的<文字边界>”,但在主题之外的“<word border> free”的出现将不算在内。

      * 100^1 ^Subject:.*\<free|sex|opportunity|money|great\>

[translates to]

^Subject:.*\<free
sex
opportunity
money
great\>

而且这个也会得分400。 怎么样? MATCH将包含整个主题,与“伟大”,“机会”和“自由”将不重叠的匹配。 如果我们摆脱了字边界标记中的一个或两个,那么它将达到500。

      Subject: Great opportunity for free sex; no money required!!!!
* 100^1 MATCH ?? ()\<(free|sex|money|opportunity|great)\>

9.2简要分析教程

#todo:test

[elijah]如果您认真使用分数,请花一分钟阅读这个简短的例子。

      VERBOSE = "yes"

:0
* 1^1 foo
* -2^2 bar
{ }
a = $=

:0
* 1^1 foo
* -2^2 bar
{
:0 f
| echo Whee: fun ; cat -
}
b = $=

:0
* 1^1 foo
* -2^2 bar
{
whee = "fun"
}
c = $=

:0 h
/dev/null

那么如果你发送消息

      From foo Fooof
To: bar
Subject foobar

body-something-here

日志文件会告诉你发生了什么。

      procmail: [20175] Fri Sep 26 10:25:23 1997
procmail: Score: 3 3 "foo"
procmail: Score: -6 -3 "bar"
procmail: Assigning "a=-3"
procmail: Score: 3 3 "foo"
procmail: Score: -6 -3 "bar"
procmail: Assigning "b=0"
procmail: Score: 3 3 "foo"
procmail: Score: -6 -3 "bar"
procmail: Assigning "c=-3"
procmail: Assigning "LASTFOLDER=/dev/null"
procmail: Opening "/dev/null"
From foo Fooof
Folder: /dev/null 46

9.3分数范围

如果您有交付Recipe并且分数为正,则执行行动线。 如果分数小于或等于0,则 $ =信息丢失,但是在下一个配方定义中,即使Recipe从不执行。 研究如下:

      :0
* 10^0
{
dummy = "Score for condition xxxx was: $= $NL"

:0
{
dummy = "Next recipe, Score no longer available: $= $NL"
}
}

# Wont' work. $= is getting set back to 0 outside of
# the delivering recipe.

dummy = "Score outside of all recipes: $= $NL"

这是有趣的异常, [理查德]发现。 这里只提出好奇心。 不要在您的餐馆使用它。 (这不是“干净的编程”,而是一个黑客)

[david]如果要保存分数供以后使用(即使为零或为负):

      :0
* 10^0
{ } # procmail no-op

SCORE = $=

:0 A
action_if_positive

如果其他Recipe扼杀A标志的参考文件干预,这将会起作用:

      :0
* 10^0
{ } # procmail no-op

SCORE = $=

... more stuff ...

:0
*$ $SCORE^0
action_if_positive

9.4计数字符串的长度

假设 VAR包含一些文本,我们可以使用点来匹配每个字符并增加每个匹配的分数来计算字符。

      :0
* 1^1 VAR ?? .
{ }

LENGTH = $=

9.5消息中的计数行(添加行:标题)

[1995-10-03 PM-L Idea by David Karr dkarr@nmo.gtegsc.com ] [david]后来更正了1998-01-02:首先,第二个条件总是算太多(最后的换行加上关闭推定换行创造额外的匹配); 第二,在进行修正之后,一个空的机体会得分为零并且保留变量未定义。

      :0
* 1^1 .
* 1^1 ^.*$
* -1^0
{ }
lines = $=

:0 fhw
* ! ^Lines:
| $FORMAIL -a "Lines: $lines"

我们使用它的原因是,尺寸条件仅在整个文本上工作,而不管配方顶部的H或B或HB标志。 现在我们可以做到这一点,并在一个条件下得到准确的数字:

      # leave `B ??' out to measure the entire message
:0
* 1^1 B ?? > 1
{ }
size = $=

如果你想愚蠢的(因为我们中的一些人经常这样做)

      :0
* -1^1 B ?? > -1
{ }
size = $=

给出相同的结果,只要搜索区域不是空的,那么这些也是非常糟糕的:

      :0
* 1^-1 B ?? < 1
{ }
size = $=

:0
* -1^-1 B ?? < -1
{ }
size = $=

[Karr]该配方计算消息中的字节数,您可以使用此内容长度替换,更喜欢使用下一个配方。 第一个分数计算每个字符,第二个分数总计每行(即添加换行符)。

      :0 H                        # use B to measure body only
* 1^1 B ?? .
* 1^1 B ?? ^.*$
{
textsize = $=

:0 fhw
* ! ^Content-length:
| $FORMAIL -a "Content-length: $textsize"
}

9.6确定身体是否长于头部

      :0
* 1^1 B ?? > 1
* -1^1 H ?? > 1
{
..body was longer
}

9.7匹配最后接收的标题

[david]这是使用得分打最底部的 Received标题的方式。

      :0
*$ 1^1 ^Received:.*by$s+\/.*
action

9.8测试值范围与打分(bogofilter)

Bogofilter将邮件添加到包含垃圾邮件的可扩散性范围的邮件中,范围为0.0 - 1.0:

      X-Bogosity: No, tests=bogofilter, spamicity=0.365761 ...

如果过滤器以MTA运行,则必须配置在canoot处影响单词“否”的值。 要直接测试结果分数,以获得范围为0.2 - 0.9的消息,可以通过评分进行“不确定”。 如果流量值为0.92,则第一分会返回:1.90 - 0.92 = 0.98,低于1分数OK值。

      :0
* ^X-Bogosity:.*spamicity=\/0\.[0-9][0-9][0-9]
{
# check for maximum
:0
* $ -$MATCH^0
* 1.90^0
{
# check for minimum
:0:
* $ $MATCH^0
* 0.8^0
{
# VAlue is betweeb A .. B
}
}

9.9如何添加Content-Length标题

我们使用procmail进行本地传递,并希望得到它来生成内容长度标题(如果不存在)。 如果没有消息体,SUN-OS mailtool至少会混淆并将消息合并。

[stephen]所有你需要做的是:a)确保procmail在没有-Y标志的情况下启动。 b)在你的sendmail.cf中,插入:

      H?l?Content-Length: 0000000000

或者(效率略低),在/ etc / procmailrc文件中插入以下配方,Procmail将会处理任何必要的魔法。

      :0 hfw
* !^Content-Length:
| /usr/bin/formail -a "Content-Length: 0000000000"

9.10测试消息大小或行数

尺寸条件在标志行上忽略 H和 B ,并且始终在 HB上工作,除非在条件自己的行上指定了另一个搜索区域。 为了测试身体,

      :0                      # Note: this is in BYTES
*$ B ?? < $NBR
{
...whatever when fewer bytes
}

该语法将遵守标志行上的B标志:

      :0                      # Note: this counts LINES
* -1^1 B ?? .
* -1^1 B ?? ^.*$
*$ $NBR^0
{
...whatever when fewer lines
}

9.11使用递归包含计数逗号

[jari]前言:David和Phil真的是procmail的专家,让这部分作为“地球上的递归procmailrc以及如何使用”的例子。 我不会亲自使用递归包含,因为我不会交易清晰度:我觉得这更容易理解和维护。 分割只是根据逗号和 打印返回爆炸输入数量有多少元素爆炸到阵列 a 。 在递归版本中,性能指标不比分叉 procmail二进制文件大。

      :0
* ^CC:\/.*
{
field = $MATCH

saved = $SHELLMETAS
SHELLMETAS
commaCount = `echo $field | awk '{print split($0,a,",")}' `
SHELLMETAS = $saved
}

请参阅<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/ cgi-bin / w3glimpse2HTML / procmail / 1997-08 / msg00073.html?50#mfs>上的递归RC实现

[理查德]这里是不需要递归的Recipe。 MAX_RECIP设置为9,但您可能更喜欢某些其他值。 这会计算每个逗号。 它允许在地址中。一些人总共Resent-xx或非Resent-xx标头。 我总结一下

      :0
* 1^1 ^(resent|apparently-)?(to|b?cc):\/.*
* 1^1 MATCH ??,
*$ -$MAX_RECIP^0
{
:0
*$ $=^0
*$ $MAX_RECIP^0
{
RESULT = "Count of commas is $="
}
}

10.0正式使用

10.1使用formail -x获取字段

如果你是新来procmail,您的第一个,但从消息中读取标题内容可能会被调用:

      SUBJECT = `$FORMAIL -xSubject:`

这不好。 不要这样做 你刚刚创建了昂贵的shell子进程,其中procmail调用formail并提供完整的消息给它。 我们可以做最少的努力:

      :0
* ^Subject:\/.*
{
SUBJECT = $MATCH
}

没有shell子进程调用。 这要快得多,资源消耗更少,而可能需要更多的打字。 使用它,您的系统管理员对您的行为良好的procmail配方感到满意,这些配方不会不必要地加载CPU。 与formail相当的可能更安全,因为它包含完整的符合RFC的解析器。 用formail导出地址的传统方式是:

      FROM = `$FORMAIL -rtzxFrom:`

但是你仍然可以使效率更高。 这里有一个例子,你实际上想使用“old” = | 样式变量赋值,确保没有额外的空格:

      :0 hw
FROM=|$FORMAIL -rtzxFrom:

这样只有标题被输入到formail中,而前面的后面的勾选提供了整个消息。 另一个好处是,您可以在此之后使用A或A配方检查formail的返回码。

10.2始终使用formail -rt开关

[菲利普]从版本3.14起,你现在应该放弃 -t 。 引用formail手册页:

默认情况下,当生成自动回复头时,procmail从输入消息中选择信封发件人。 对于关于原始邮件的路由或传递的休假消息和其他自动回复,这是正确的。 如果发件人期待回复或响应于原始消息的内容生成回复,那么应该使用-t选项。

10.2.1对于前3.14版的procmail版本

[FAQ] -r打破RFC822,所以总是用-rt,如果你不知道这是什么意思。 也许你应该总是使用它。

[david]在3.11pre4的源代码中有formail -r t rank bar图。 从顶部到底部的列表可能更容易遵循(再次,Tom Zeltwanger似乎正在使用其中From_被错误地提升的旧版本)。 这些是版本3.11pre4中的排名:

      formail -r:                     formail -rt:

Resent-Reply-To: Resent-Reply-To:
Resent-Sender: Resent-From:
Resent-From: Resent-Sender:
Return-Receipt-To: Reply-To:
Errors-To: From:
Reply-To: Sender:
Sender: Return-Receipt-To:
From_ Errors-To:
Return-Path: Return-Path:
Path: From_
From: Path:

始终使用-rt而不是-r 。 因为这样的优先级(Sender over From)是对RFC 822的一个重要的违反。有一个规范的顺序,在RFC中描述,没有其他应该被使用,如模糊排名,或者更糟的是重新排序。 这是一个严重的问题。

正确的顺序是:

      Reply-To, else From, else Sender, else <error>

而且,你如何处理重复邮件? 即:Resent-Reply-To,Resent-From和Resent-Sender?

它将Resent-X视为X(“每当字符串Resent-开始字段名称时,该字段与名称不具有前缀的字段具有相同的语义”。)。 所以你必须在它们之间选择一个顺序,RFC没有指定它。

[david]我认为这个想法是-r旨在确定起源地址,而不是回答的地方; -rt是用于确定发送回复的地方。 为了解决响应,是的, -rt将以更符合规则的方式将报头反转; 为了找出起点,

      formail -r -zxTo:

可能比

      formail -rt -zxTo:

这里还有一个问题: formail -rD始终使用-r的优先级; 您不能同时使用-rt优先级和-D缓存检查功能。

4.4.4。 FROM / SENDER / REPLY-TO(RFC 822摘录)的自动使用

对于自动生成回复邮件地址列表的系统,提出以下建议:

  • 发送方字段邮箱应在发送或发送原始邮件时发送任何问题的通知。 如果没有发件人字段,则应使用“ 发件人”字段邮箱。
  • 发件人字段邮箱不应该在收件人的回复邮件中自动使用。
  • 如果回覆字段存在,则答复应转到该字段中指示的地址,而不是发送到“ 发件人”字段中指示的地址。
  • 如果有“发件人”字段,但没有回复字段,应将答复发送到“发件人”字段中指示的地址。

有时,接收者可能希望与发起消息传送的人进行通信。 在这种情况下,使用发件人地址是合理的。

此建议仅用于发起者字段的自动使用,并不意图表明答复也可能不会发送到消息的其他收件人。 由各自的邮件处理程序决定将提供哪些附加设施。

10.3使用-rt并重写From地址

Sendmail添加了指向您帐户的 From头。 但在某些情况下,您可能希望重写 From 。
  • 你回复垃圾邮件发送者,你想在某种程度上隐藏你的地址。 (标题仍然会在那里,但是在大多数MUA中,至少打到了“ 从”开始 )
  • 您想要重写From以显示您的虚拟地址me@forever-lasting-address.com。
  • 您目前在其他帐户中,但您想要发送消息到一些Net服务(例如邮件列表),希望看到您第一次使用订阅的地址。

您还可以使用回复来表示您希望进一步回复的位置,但不会隐藏您的真实发件人地址。 而且还有MUAs不服从回复 。 无论什么原因你必须重写从头,这里是命令。

      :0 fhw
| $FORMAIL -rt -I "From: me@forever-lasting-address.com"

10.4 Formail -rt和Resent-From头文件

这是一个让我刮伤我头脑的东西。 我们先来看一下解释邮件运行方式的场景。

      account --> virtual-address --> Local-address

在这个链中,我将邮件从我的一个帐户发送到另一个地址, 虚拟地址将邮件发送到正确的本地域。 这张照片只有一个问题。 当使用formail -rt从本地地址生成响应时,生成的地址指向虚拟地址 ,当然指向本地地址 。 回来已经准备好了,您无法获得前往原始地址的路线: 帐户

这里发生的是处理虚拟地址的邮件服务器没有转发邮件,而是重新发送邮件。 在此过程中,生成了一组新标题:

      Resent-From: <virtual-address>
X-From-Line: <account>
Received: from <the virtual-address mailserver>
Resent-Message-Id: <199710151903.WAA28670@virtual-address>
Resent-Date: <date>
Resent-To: <local-address>
Received: ...<account domain>
Message-Id: <199710151904.WAA05050@account-domain>
From: <account-domain>

现在,当使用formail -rt命令时,它会拾取应该返回消息的Resent-From添加的目的地。 令人惊讶,但根据procmail,100%正确。 Resent-From具有比From更高的优先级。

Resent- *标题被认为是信息性的 ,在自动生成响应时不应使用。 这里的问题是中间人,不应该重发信息,而是转发它。 所以我把它放入我的.procmailrc来处理我们网站中断的中间人。

      #   Remove that misleading Resent-From if it was added by our
# "middleman"

:0 fhw
* Resent-From: <our-domain>
| $FORMAIL -IResent-From:

[edward]补充说:正如你所知, formail -rt是用于撰写对发送电子邮件的地址的响应。 假设您正在度假,并设置了一个procmailRecipe来自动回复您收到的所有电子邮件。 此外,我们来说,Joe给我发一个电子邮件,我把它重发给你。 如果你想回复你收到的电子邮件的发件人,你会给我发电子邮件还是乔? 你最好给我发电子邮件,因为我是发给你的人。 乔甚至可能不认识你 想像一下,如果你确实发送了你对Joe的回复。 这可能会导致他相当混乱,为什么你给他发电子邮件通知他你是假期。

formail -rt使用启发式算法来根据各种头文件及其内容的存在来确定应该响应哪一个。 如果您查看formail.c源代码,您将看到该算法的图形表示。 它还将解释-r和-rt的结果之间的差异。

Resent-Reply-To具有所有头域的最高相对重要性/可靠性。 接下来是Resent-From和Resent-Sender,其次是Reply-To,From,Sender等。

10.5引用消息

使用formail -rtk

10.6没有引用消息

使用formail -rkb或formail -rkt -p“

10.7如何将标头和正文包含在回复信息中

这个想法是您首先将整个头部捕获到变量中,然后将其添加到消息体中。 这里一个自定义消息被添加到开头和下一个标题。 请注意,原始身体已由 rtk添加。 一定要把这个空间放在大括号里面 他们很重要

      #todo:

:0
* ^^\/(.+$)+$
{
header="$MATCH"
}

:0 fhw
| $FORMAIL -rt; ... now generate reply ...

10.8添加文本到消息的开头

我们实际上并不过滤任何东西。 这只是一个重新打印标题的技巧,并在文本后添加一些文本:文本显示在正文的开头。

      :0 fhw
| cat - ; echo "This text comes after the headers."

10.9添加文本到消息的末尾

      :0 fb
| cat -; echo "added text after body"

10.10引用消息之前添加文本

如果您要生成一个自动回复消息,您希望将通知发送到正文的开头,然后是引用的原始消息,这里是它的配​​方。 替代 条件触发回复条件。

      :0
* condition
{
:0 fhb
| $FORMAIL -rtk -p '>' \
-I "From: me@here.com" \
-I "$MYXLOOP"

:0 fhw
| cat -; echo "added message at the start of body"
}

12.10如何截断头文件(保存文件空间)

[Idea by Rodger Anderson <rodger@hpbs2245.boi.hp.com>]作为最后的Recipe,如果你的空间很小,你可以删除无关的标题。 但是请确保您想要这样做,因为标题可能包含有关URL和其他东西(如邮件服务器地址)的有用信息。 有些人将签名信息保留在单独的X-header(例如: X-My-Info )中,而不是在消息的底部,这样它不会打扰人们并打扰回复引用。

      #   Strip header to bare minimum
# If this is MIME multipart, then skip recipe

:0 fhw
* ! multipart
| $FORMAIL -k \
-X Date: \
-X Subject: \
-X Message-Id: \
-X From \
-X To: \
-X Cc: \
-X Reply-To: \
-X Mime-Version: \
-X Content-type:

:0 :
mail.default.mbox

[大卫]评论最后的Recipe

  • 你应该保持Reply-To标题,如果有的话。 如果发件人希望回复指向与From头文件不同的地址,则会丢失该信息,并在您回复时写入错误的地方。
  • 你应该保持To和Cc ,以便您可以在阅读邮件时知道谁发送了它。 如果您的邮件用户代理具有组回复或全部回复功能,则保持“ 收件人”和“ 抄送”将允许该功能继续工作。 这样你就会欺骗自己。
  • '-X From'足以保留From_行和From头。 您不需要再次指定-X From:。 (要保持From_ without From:你需要说-X“From”或类似的东西,带引号的空格。)
  • 所有的邮件都将有一行(通常是两个),从'开始'开始。

另一个稍微不同的方法是杀死占用大部分空间的头文件。 如果您不想跟踪可能的UBE消息的原始发件人,那么可以删除Received标头。 您可能需要填写条件行以简化您的工作或校园消息,并让其他消息保留其完整标题。

      :0  fhw
* possible-condition-to-handle-only-certain-messages
| $FORMAIL -I Received:

10.11从文件中添加额外的头文件

请注意,明显的解决方案不会在这里:

      :0 fhw
* condition
| $FORMAIL -rt | cat - $HOME/newHeaders

这里的问题是中间会有一个换行符,这样会导致头缩短(procmail在处理每个过滤器之后确定新的标题/体边界)。 使用以下代替。

      :0 fhw
* condition
| $FORMAIL -rt -X "" ; cat $HOME/pm-newHeaders.txt ; echo

[david]如果$ HOME / newHeaders以空白行结束,则不需要“; echo”。 在某些情况下,procmail如果丢失了空白分隔线,但我不确定这些是什么,并且您已经有一个SHELLMETAS字符(第一个分号),所以一个shell是分叉的。

但这是我最喜欢的方式(它假定formail -r永远不会为From :)生成连续行; 如果您使用它,请确保newHeaders文件不包含尾随空白行:

      :0 fhw
* whatever
| $FORMAIL -rtn

:0 A fhw
| sed "/^From:/r $HOME/newHeaders"

10.12分解摘要

[David Hunt的想法 ]一个有趣的想法,作为单个消息自动处理摘要,如果我们递归调用procmail。 第一个调用formail来分割邮件,当headerfields包含在body中时,再次调用procmail作为formail的输出程序。 X-Loop插入使得可以为单独的消息重新使用 〜/ .procmailrc 。

      #   If it more than one mail, send to formail for
# splitting, then send back to procmail for sorting again.

:0
* B ?? ^From [-_+.@a-z0-9]+ (Sun|Mon|Tue|Wed|Thu|Fri|Sat)
* B ?? ^From:
* B ?? ^TO
*$ ! H ?? ^$MYXLOOP
| $FORMAIL -A "$MYXLOOP" -m4s procmail

10.13邮箱:拆分为单个文件

[david]要将一些旧的邮件存档拆分成单个文件,同时剥离不重要的标题字段,请使用以下命令。 密钥是使用procmail的 -p选项,在 DEFAULT的设置中强引用 $ FILENO ,并使用/ dev / null或已知的空文件作为rcfile。

      % setenv FILENO 0000
% formail -kXDate: -XFrom: -XTo: -XSubject: -XIn-Reply-To: \
-XX-Mailer +1ds \
procmail -p DEFAULT=`pwd`/'$FILENO.txt' \
/dev/null < inputfile

10.14邮箱:从邮箱中提取所有从地址

-ns选项使formail拆分邮箱,并将每个邮件分别提供给下一个进程。

      % formail -ns formail -xFrom: < mailbox | sort -u

10.15邮箱:在整个邮箱中应用procmail配方

      % formail -ns procmail pm-experiments.rc < mailbox

10.16邮箱:为每个邮件(拆分邮箱)运行一系列命令

...也许热量融化了我的大脑,但是我似乎无法在每个邮件上从文件夹中分割出一系列命令。 以下是一个简单的调试尝试的例子:我已经尝试了括号,将命令放入一个shell函数中,而其他的flailings也无数记住了,一切都没有了。

      % formail -s addr=`formail -XFrom: | formail -r | formail -zx To`;\
echo "$addr" >>output

执行分割时指定的命令时,formail不会使用shell。 没有SHELLMETAS在这里 鉴于此,秘密是明确地启动外壳做管道:

      % formail -s sh -c 'formail -XFrom: | formail -rzxTo:' >> output

请注意,在管道中只需要两个formails,而不是三个,因为-r标志与其他标志组合时正常工作。

...对我来说,一个大邮箱每月将包含大约10,000封邮件(这是我所得到的)。 这意味着我的邮箱将在6个月内收到6万条信息。 我确定,因为它不会想要全部了解甚至尝试加载在MUA。

[1998-08-27 Bennett Todd bet@mordor.net ]我也处理怪兽的邮件。 我在所有邮件处理中完全切换到Maildir; 我仍然看到mbox的唯一的地方是在我的netnews阅读(使用slrn)的保存文件夹中,每当我想处理它们时,我将它们转换成Maildir(例如用于归档)或者简单地将它们分成多个消息。 分裂成多个消息证明是非常简单的; 使用GNU csplit:

[richard]这里显示的csplit调用会捕捉到^如果您的MUA没有使用>将它们转义,就嵌入到邮件正文中。 一些MUA使用内容长度标头,不能从^ From转义。 Procmail支持这一点。 如果您选择使用这个简单的拆分,请谨慎。

      csplit -n4 - '/^From /' '{*}'

这将创建一个空的xx0000,我删除,并将消息留在名为xx0001,xx0002等的文件。如果一个文件夹中有超过9999个消息,然后转到-n6或-n9或任何。 一旦拆分就可以很容易地使用shell工具将邮件捆绑在一起,将其归类到类别等中。

如果你正在归档所有的邮件流量(我做的),那么添加到组合中的另一个dandy工具是一瞥http://glimpse.cs.arizona.edu/它需要一段时间来构建索引,但这是一个很好的工作在晚上用完了cron。 一旦建立索引,这是一个快速的方式来根除大型邮件。

10.17选项-D和缓存

[Bob Weissman b_weissm@kla.com ][stephen]这些文件是自限制的。 -D后的数字是以字节为单位的大小,较旧的条目将被删除。 例如,我的.procmailrc有

      :0 Wh:  .msgid.cache$LOCKEXT
|$FORMAIL -Y -D 12288 .msgid.cache

文件不会超过12288个字节。 虽然formail确实超过了这个大小,只要一个消息ID的长度,文件大小决不会显着超过这个大小,即使无限期地使用。 该文件为二进制格式,每个条目以单个空字节终止,偶尔(重要占位符)为双null

[philip]缓存的格式最初如下:

      entry\0entry\0entry\0\0

当文件大小增加到等于或大于命令行上指定的大小时,formail将从头开始,使用双null来标记它停止的位置。 但是,除了部分覆盖的条目之外,双null后的条目仍然有效并被检查,因此该文件的格式为:

      entry\0entry\0entry\0\0partial-entry\0entry\0entry\0\0

新条目将在第一个双null后写入,以便它实现一个循环缓存。 查看formail.c的第319-322行

10.18选项-D和消息id在正文中

我的一些消息包含字母正文中的原始Message-ID,而不是标题。 Formail有没有选择来解决这个问题?

[david]这是严格未经测试的; 我不知道身体中的消息ID出现在哪里,但如果他们在身体的顶部,这可能有助于:

      :0 hW        # Message-Id: in the head,
*$ ^Message-Id:.*$NSPC
| $FORMAIL -D $cache_size $cache_name

:0 E bW # If not but there's one the body, try body.
*$ B ^Message-Id:.*$NSPC
| $FORMAIL -D $cache_size $cache_name

在任何情况下,您可能希望将Message-Id从身体复制到头部(如果头上没有),只需将其放在正确的位置,那么我们可以先执行此操作,然后直接 -D将正常工作。 如果Message-Id头部在主体而不是头部,则此表单将运行两次,但它将在正文的 任何行上寻找Message-Id ,而不仅仅是在顶部:

      :0 fhw
*$ ! H ?? ^Message-Id:.*$NSPC
*$ B ?? ^\/Message-Id:.*$NSPC
| $FORMAIL -A "$MATCH"

:0 hW
| $FORMAIL -D $cache_size $cache_name

10.19减少formail调用(有条件地添加字段)

#todo:url

假设您需要在满足某些条件时向消息添加字段:

      :0              # compose initial reply
| $FORMAIL -rt

:0
* condition1
| $FORMAIL -A "X-Header1: value1"

:0
* condition2
| $FORMAIL -A "X-Header2: value2"

嗯,我们这里有三个进程,我们可以尽量减少通话吗? 是的,这是[philip][david]的想法。 请注意,只需要一个进程。

      :0
* condition1
{
hdr1 = "-AX-Header1:value"
}

:0
* condition2
{
hdr2 = "-AX-Header2: value"
}

:0 fhw
| $FORMAIL -rt ${hdr1+"$hdr1"} ${hdr2+"$hdr2"}

而且如果你想把所有的标题成一个变量,这是一个额外的工作。 下面我们使用简短的变量名,只因为行空格:调用适合一行。

  • field = all(f)堆叠成一个字符串。
  • nl =以前字段的续行换行符

配方说:如果字段具有以前的值,请将nl设置为换行符分隔符,稍后使用可能的换行符和新标题字段连接字段的先前内容。

      field       # kill variable
:0
{
nl
nl = ${field+"$NL"}
field = "$field${nl}X-Header1: value"
}

:0
{
nl
nl = ${field+"$NL"}
field = "$field${nl}X-Header2: value"
}


:0 fhw # If we have something in *field*
* ! field ?? ^^^^
| $FORMAIL ${field+-A"$f"}

上述Recipe是最通用的Recipe,每个Recipe本身如果f存在于先前而不是确定。 但是如果你知道f已经设置好了,你可以编写更简单的Recipe:

      :0          # We know f has value before our module
{
field = "$field${NL}X-Header1: value"
}

10.20 Formail -A -a选项

如果标题名称相同,则不能使用-a或-I选项-A。 像下面的那样,您尝试仅保留X-1的最后一个定义,但是在应用-a时看不到第一个-A。

      formail -A "X-1: 1" -a "X-1: 2"
-->
X-1: 1
X-1: 2

而而 单独的管道给你想要的结果。

      formail -A "X-1: 1" | formail -a "X-1: 2"
-->
X-1: 1

formail -A "X-1: 1" | formail -I "X-1: 2"
-->
X-1: 2

10.21 Formail -e -s选项

[david]我有一个交替的 From和 Date行的文件,并希望将其转换为mbox。

      formail -dem2 -s < input > mailbox

应该做到了,对吧? 不; formail -s将其全部作为一个消息,即使使用-m1。 当我编辑空白行时,命令工作。 我的第一个反应是,-e选项没有像广告一样工作,空白行毕竟是必要的。

然后我意识到了真正的问题:输入中有效标题行的连续性并不会中断,任何可能看起来像一个身体的东西。 我可以在每对标题字段之间放置除空白行之外的东西,然后-e将完成其工作,但只要每个附加行看起来像一个有效的RFC822标题字段,即使其名称与早些时候出现, formail -s假设它仍然是同一个消息的头。

11.0保存邮件列表消息

11.1使用子程序pm-jalist.rc来检测邮件列表

因为我没有sendmail加寻址功能(下文将介绍),我写了模块 pm-jalist.rc 。 它包含在pm-code.zip中

子程序尝试直接从消息中检测并导出邮件列表名称。 许多邮件守护进程:ezlm,smarlist,listserv,majordomo使用标准化的头文件,从中可以选择列表名称。 在该子程序应用于消息之后,变量LIST包含邮件列表名称。 您不再需要为每个订阅的新邮件列表手动插入单独的Recipe,因为这个子程序自适应地找到新的邮件列表。

一旦邮件列表名称被抓住,您可以轻松地“映射”或将名称转换为任何合适的文件夹名称,然后再保存:

      LIST            LIST name    Description of mailing list
(as grabbed) you want
--------------------------------------------------------------
jde java.jde Java Development Env
java java.prog Java programming
FLAMENCO flamenco Flamenco music
tango-l tango Argentine Tango dancing
tm-en-help tm-en Emacs TM mime package mailing list
w3-beta w3 Emacs WWW mailing list

您设置然后转换抓取LIST到具有转换表的新文件夹名称:

      JA_LIST_CONVERSION = "\
jde java.jde,\
java java.prog,\
FLAMENCO flamenco,\
"

为了检测所有邮件列表,您只需要一个配方,如下所示:

      INCLUDERC = $PMSRC/pm-jalist.rc

:0 : # if list name was grabbed
* ! LIST ?? ^^^^
$LIST_SPOOL_DIR/list.$LIST

11.2使用加号foo+bar@address.com

如果您最近有足够的(8.8.8+) sendmail ,请问您的系统管理员是否激活加号。 Procmail自动获取 $ 1的条形码。

http://www.faqs.org/faqs/mail/addressing/

[Bennett Todd bet@mordor.net ] PLUS功能也在qmailPostfix (nee VMailer)中实现。 默认情况下,qmail使用“ - ”而不是“+”,但可以配置为使用不同的规则; Postfix没有启用,但其示例main.cf具有注释的行,以启用“+”支持。

[Roy S. Rapoport rsr@macromedia.com ] Plus寻址使用sendmail实现(好的,我相信其他的MTA也可以这样做,但是我的经验是使用sendmail)。 sendmail的最后几个版本(8.8.6,8.8.7,8.8.8)似乎都自动默认允许。 基本上,对于foo + baz格式的任何地址,sendmail将忽略+ baz部分,并将其传递给foo。

如果您想要最简单的方法来处理邮件列表邮件,那么请使用专用的加号订阅列表:

      login+list.procmail@example.com
login+list.debian@example.com
login+list.linux@example.com

当您从任何这些邮件列表收到您的登录帐户的消息时, list.procmail已经在变量$ 1中 ,并且将所有邮件列表汇集到其各个文件夹的配方非常简单:

      #   Note: The $1 contains value only _IF_ procmail
# is invoked with option -m or -a (with an argument).
# Be sure procmail is invoked with that oprion either as from
# LDA or ~/.forward.
#
# $1 is pseudo variable and it can't be used in condition line,
# so we copy the value to ARG.

ARG = $1

:0 :
* ARG ?? list
$ARG

[david]这是我配置为sendmail.cf以支持加寻址:

      Mprocmail, P=/usr/bin/procmail, F=DFMmShu,                      \
S=11/31, R=21/31, \
T=DNS/RFC822/X-Unix, \
A=procmail -m $h $f $u

那么这是procmail邮件程序的定义,而不是本地邮件程序。 此外,与本地邮件程序的定义相比,还有更多的寻址支持。 需要将规则集0或5设置为将+之后的所有内容移动到“主机”变量($ h)中。 除非您对sendmail规则集和重写规则有很强的理解,否则您不应尝试向sendmail.cf添加加号,而只是安装最新版本的sendmail,并使用m4 sendmail.cf生成工具。 mc文件包含:

      FEATURE(local_procmail, `/usr/local/bin/procmail')

加上你的网站所需要的任何东西。

      ...Ok, I corrected it. Well, here's what that looks like. I did
look into the part about Ruleset 5 while trying it on
originally. But all I could do was make sure that the
plus-addressing section was there.

Mlocal, P=/usr/bin/procmail, \
F=lsDFMAw5:/|@qSPfhn9, S=10/30,
R/40,
T=DNS/RFC822/X-Unix,
A=procmail -Y -a $h -d $u
Mprog, P=/bin/sh, F=lsDFMoqeu9, S=10/30, R/40, D=$z:/,
T=X-Unix,
A=sh -c $u

11.3使用RFC注释技巧获取更多信息

[rfc1036]回想,首选的Usenet邮件地址格式如下

        From: login@example.com
From: login@example.com (First Surname)
From: First Surname login@example.com

在阅读Eli关于邮件寻址的优秀常见问题之后,我发明了这个想法。 请继续阅读(特别是第19节),以了解我将要呈现的内容。

我有一个不支持加号的帐号,我对所有可以使用这个整齐的sendmail寻址方案的人感到嫉妒。 加号解决方案有助于更好地处理邮件列表消息。

但事实证明,我们可以在一定程度上模拟与纯RFC符合地址的寻址。 我们利用RFC注释语法,其中注释是括号内的任何文本。 根据以利文件,过境时应保留意见。 他们可能不会出现在原来的确切位置,但这不应该是一个问题。 所以,我们发送消息带有以下From或Reply-To行:

      first.surname@domain (First Surname+list.procmail)

现在,当有人回复你时,MUA通常按原样复制该地址,您可以在接收端读取PLUS信息,并将邮件删除到相应的文件夹: mail.procmail 。

[关于使用RFC comment-plus地址订阅邮件列表]

非常不幸的是,当您订阅列表时,当您添加到列表数据库时,注释不会被保留。 只保留地址部分。 我甚至将角色里的评论置于愚蠢的程序中,以便在角度之间取得一切。

      first.surname(+list.procmail)@example.com

但我没有运气。 他们有很好的RFC解析器,它会丢弃并清除这样的注释。 例如。 基于procmail的邮件列表,着名的Smartlist ,使用formail导出返回地址和formail不保留注释。 上面被截断

      first.surname@example.com

还有许多邮件列表发送邮件为密件抄送 ,所以您的地址甚至不能在标题任何地方,这也不是很好的RFC评论。 好的,但是这个RFC的评论技巧在私人通信中运作良好,几乎所有的MUA都将From或Reply-To标题的全部内容复制到To头,保留注释,并获得加号的好处。 这里是procmail代码来演示从RFC comment-plus字段读取PLUS信息:

      RC_EMAIL = $PMSRC/pm-jaaddr.rc      # Address explode module

:0
*$ To:\/.*
{
INPUT = $MATCH
INCLUDERC = $RC_EMAIL # Explore grabbed To address

# If COMMENT_PLUS was defined, module found "+"
# address which contained, say, "mail.procmail".
# Save it to folder.

:0 :
* COMMENT_PLUS ?? [a-z]
$COMMENT_PLUS
}

很简单 你可以把任何内容放在RFC评论中,并用这些加号做任何你想要的。 注意 :不保证每次都保留RFC注释。 那么标准的RFC822说是必须通过的,但是我会说邮件是从一个服务器传递到另一个服务器的情况的90%。

示例:如果您在Usenet组中讨论,可以使用地址

      first.surname@example.com (First Surname+Usenet.default)
first.surname@example.com (First Surname+Usenet.games)
first.surname@example.com (First Surname+Usenet.emacs)
first.surname@example.com (First Surname+Usenet.linux)

11.4简单邮件列表处理

[Peter S Galbraith galbraith@mixing.qc.dfo.ca ]我以前用过这个(只需看看spool文件并看到消息的 From_行):

      :0 :
* ^From debian
list.debian.mbox

:0 :
* ^From procmail
list.procmail.mbox

现在,我将特定的大量邮件列表(如Debian)收集到如上所述的自己的假脱机文件中,并让其他配方将所有其他邮件列表(如procmail和fvwm)捕获到稍后规则的单个假脱机文件中:

      :0 :                                    # Majordomo lists
* ^Sender: owner-\/[-a-zA-Z0-9_.]*
list.$MATCH.mbox


:0 :
* ^X-Mailing-List: <\/[-a-zA-Z0-9_.]* # SmartList lists
list.$MATCH.mbox

所以Debian邮件列表邮件去Debian,procmail和fvwm邮件去邮件列表和邮件发送给我,但CC'ed到一个列表去我的主要假脱机文件。

11.5根据TO归档

传统的检测和保存邮件列表消息的方法是:

      :0 :
* ^TO()procmail
list.procmail

[and so on...]

以下代码将在TO地址中将该消息保存到文件夹list.foo,list.bar,list.procmail。

      #   generalised version
# By dattier@wwa.com (David W. Tamkin)
# cases desired for foldernames

LISTS = "(foo|bar|procmail)"

:0:
*$ ^TO_()\/$LISTS
*$ LISTS ?? ()\/$\MATCH
list.$MATCH

11.6使用Return-Path检测邮件列表

[philip]对于大多数邮件列表,确定是否来自列表的更准确的方法是检查Return-Path:,From_或Resent-From:header。 这可以从列表中捕获消息,无论它们是否为To:列表,Cc:列表,甚至是密件抄送:列表,完全不显示在消息中。

例如,我使用以下配方从procmail邮件列表中回复消息:

      :0
* ^Return-Path: +<procmail-request@informatik
~/Lists/procmail/.

有一个棘手的事情要注意:如果有人向我和列表发送消息(比如,回复我发送到列表的消息),那么通过列表获得的副本将最终在我的procmail文件夹中,而直接去的副本不会。 我喜欢这种行为,但是有些人(可能是你自己)可能会喜欢这两个消息最后重新提交。 如果是这样,最好的办法是通过^ TO_标记来将上述与To:和Cc:头文件进行匹配。

      :0
* ^Return-Path: +<procmail-request@informatik|\
^TO()_procmail@informatik
~/Lists/procmail/.

(如果您在3.11pre4之前有procmail版本,则需要使用“^ TOprocmail”而不是“^ TO_procmail”)。 如果您订阅了许多邮件列表,这里是一个通用的配方

注意 :您不希望包含在Recipe中:^ TO _ \ \ \ / $ LISTS,因为^ TO_标记包含类似于\ <但是更好,所以\ <只能导致问题。 拖尾\>不是一个坏主意,尽管因为它不是零宽度断言,而是一个实际的字符类,你必须从匹配中删除它

      LISTS  = "(foo-list|bar-list)"

# 1) to get the match
# 2) rematch sans the trailing \>
# 3) Note: preserves capitalization of the string

:0
*$ ^TO_()\/$LISTS\>
*$ MATCH ?? \/$LISTS
*$ LISTS ?? ()\/$\MATCH
{
M = $MATCH
<action>
}

[Era]给出了这个示例来描述上面发生的事情:

      VAR =  "MOO"
what = "(moo|bar|baz)"

:0 # Search what from VAR
*$ VAR ?? ()\/$what
{
# Now; what is was that really matched, there were several
# choices: moo,bar,bar
# Beware: $MATCH must not contain regexp characters

:0
*$ what ?? ()\/$MATCH
{ } # no-op

# Fine, New MATCH contains moo
}

12.0 Procmail,MIME和HTML

12.1 Mime参考书目

各种MIME实现的令人讨厌的事情的列表。
...结果是生成MIME的事物的实现者的一种风格指南。 随意发送评论或贡献。 http://www.cs.utk.edu/~moore/mime-style.html

12.2 Mime音符

<URL: http : //www.xray.mpe.mpg.de/mailing-lists/procmail/1998-07/ msg00248.html>

[1998-07-28 PM-L Brett Glass brett@lariat.org ] MIME文件缓冲区溢出错误描述在

      http://www.sjmercury.com/business/microsoft/docs/security0728.htm

这个bug特别阴险,因为它可以被垃圾邮件软件利用,并可能在很短的时间内影响到数百万用户。

使用procmail插入邮件服务器上的漏洞,通过截断MIME头中的过长的文件名:消除超长的文件名,将其截回(最多)为64个字符? 所需要的只是识别下面的标题,并确保<verylongname>被切碎到合理的大小。

      Content-Disposition: attachment; filename="<verylongname>"

[时代]我认为问题并不是真正的文件名超过了一些平台允许的长度(Macintosh可以允许像27个字符,如果内存),但是一些特定的邮件客户端分配内存为文件名字符串的错误(但我真的只是在这里猜测)。

...到目前为止,Eudora,Netscape Mail,Outlook Express和mutt(Unix)都被发现有缓冲区溢出问题。 (mutt-0.93.2i及以上是固定的,0.93.1的补丁可用。)

12.3处理mime或HTML的软件

另请参见最近的Perl CPAN模块, http://www.perl.org/ site和CPAN / modules / by-module / MIME /

还有Unix程序munpack可以分解一个MIME消息来分离文件。

[Unix中的MIME感知邮件代理]

看到可以处理HTML邮件的mutt 。 (下面提到的指向Mutt的指针)

如果您安装了一些mime处理包,则所有Emacs邮件代理可以处理MIME:TM,SEMI,rmime.el。 见http://www.bmrc.berkeley.edu/~trey/emacs/mime.html

12.4 MIME类型应用程序/ ms-tnef

...我的一个邮件列表的成员似乎使用Microsoft Mail。 他的列表中的消息通常伴随着我这样一个编码的附件:“c:\ eudora \ users \ steven@idma.com \ attach \ WINMAIL11.DAT”消息头包括以下子句:Content-Type:multipart /混合 boundary =“openmail-part-058c9f3d-00000001”这是让人疯狂的。 是什么原因造成的,有什么办法让它停止吗?

发送方很可能使用Exchange(或Windows Messaging或Outlook97),并以RTF格式发送消息。 它将RTF消息放在一个名为WINMAIL.DAT(application / ms-tnef)的附件中。 但这个附件是没用的,除非收件人也在使用Exchange。

发件人可以将RTF选项关闭给您的消息。 有关详细信息,请参阅:XCLN:以富文本格式发送消息http://support.microsoft.com/support/kb/articles/q136/2/04.asp

捕获HTML mime消息

[era]这是一个简单的过滤器,可以抛出使用mime发送的不需要的HTML。 [jari]此配方检测消息是否被分类为MIME 文本/ HTML ,并将其分解为单独的文件夹。 它不会更改消息内容。 如果要从消息中实际删除HTML或其他附件,请参阅模块列表中的 pm-jamime-kill.rc 。

      :0:
*$ ^Content-Type:$s*multipart/(mixed|alternative);\
$SPCNL*boundary="?\/[^;"]+
*$ B ?? ^--$\MATCH\$([-a-z]+:.*)*Content-type:$s*text/HTML
junk.html.mbox

可以从以下部分找到更多的例子:'说明^^和^'

12.6抱怨HTML消息

[Marek Jedlinski eristic@gryzmak.lodz.pdi.net ] 。 这样我如何回应HTML消息。 在我的 noHTML.txt中,我礼貌地解释为什么我不喜欢接收HTML邮件,并要求以纯文本重新发送消息。 在大多数情况下,发生的是发件人再次重新发送相同的消息(“哦,它反弹,让我们再试一次”),我假设他们没有真正读取我的解释,因为他们只是高兴地重新发送HTML cr * p。 它再次弹跳,在这一点上他们放弃了...艰难的运气,我说;)

BTW,上述Recipe放在邮件列表邮件分类后。 当有人将HTML邮件发送到邮件列表时,我读到,我只是将他们亲自烧毁

      TXT_NO_HTML = $HOME/noHTML.txt

:0
* ! H ?? ^FROM_DAEMON
*$ ! H ?? ^$XLOOP
* HB ?? ^Content.Type.+multipart.alternative
* HB ?? ^Content.Type.+text.html
{
LOG = "$NL --TRASH: multi-part HTML $NL"

:0
| ($FORMAIL \
-rtk \
-A "X-Mailer: Procmail Autoreply" \
-A "$XLOOP" ; \
cat $TXT_NO_HTML \
) | $SENDMAIL
}

12.7将HTML正文转换为纯文本

注意:老年人有安全漏洞: http : //ciac.llnl.gov/ciac/bulletins/h-82.shtml http://lynx.browser.org/

将HTML体转换为纯文本的最流行的解决方案是使用lynx 。 另一个更简单的方法是使用perl一个内衬:它更快,更容易使用procmail,但它并不假装知道HTML DTD。 下面的Recipe应该用盐粒:看到HTML标签不能保证身体“只有”具有HTML。 谨慎的Recipe作者也观看MIME多部分消息。 (见pm- jamime.rc从消息中画出一些mime特征)

此配方已编写,以便您可以添加更多替代的HTML转换脚本。 您甚至可能想要为消息选择适当的转换:例如,对于不重要的转换,perl。

注意 :这是检查body是否包含HTML的过于简单的方法。 在这里也可以检查指示HTML编码的mime标头。

      :0
* B ?? ()<HTML>
* B ?? ()</HTML>
{
conversion = "lynx" # or select this conditionally

:0
* conversion ?? lynx
{
# In new lynx version you can read from stdin. If
# /dev/stdin doesn't exits try /dev/fd/0
#
# lynx -dump -force_HTML -nolist -restrictions=all \
# /dev/stdin
#
# Without a global lock on this, you have a chance
# that two procmail instances will try to write to
# msg.dump

file = "$HOME/tmp/msg.dump"

LOCKFILE = $file$LOCKEXT

:0 fbw
| cat > $file && lynx -dump $file

LOCKFILE

}

:0 E fbw
| perl -0777 -pe 's/<[^>]*>//g'

}

12.8摆脱不需要的MIME连接(HTML,vcard)

微软和Netscape MUAs正在征服PC世界,您可能会收到使用此软件的人的消息。 不幸的是,你收到mime格式的消息:

      HEADERS
--mime-boundary
plain text
--mime-boundary
Some idiotic HTML (or other type) copy of the text
--mime-boundary

当您希望以格式显示传统邮件时:

      HEADERS
plain text

好消息。 有一个procmail模块解决这个问题。 该模块可以杀死任何MIME连接,并且预定义的集合包括典型的情况:

  • Microsoft Explorer具有在消息结束时包含7k应用程序/ ms-tnef附件的不良习惯。
  • Lotus Notes发送类似的附加附件。
  • Microsoft Express会在附件中发送HTML格式的邮件副本。
  • Netscape的Mozilla会以HTML格式发送邮件副本。 参见示例。 它也发送烦人的vcards 。

该模块称为pm-jamime-kill.rc ,并包含在Jari的pm-code.zip中 。 (注: Procmail模块列表

12.9将纯文本中的HTML页面的内容发送给某人

[timothy]发送邮件主题:“GetPage:some.url.here/”。 它回来了。 Kurt Thams thams@thams.com还指出,lynx允许 file://协议,因为procmail正在运行,这将是一个安全隐患。

      GetFile: ~user/.login

我们通过强制“ http:// $ MATCH”使脚本安全。 而不是简单地使用“$ MATCH”

      :0
*$ ^Subject:$s+GetPage:()\/.*
*$ ! ^$MYXLOOP
| ($FORMAIL \
-rt \
-I "Precedence: junk" \
-I "Subject: Requested page: $MATCH" \
-I "$MYXLOOP" ; \
lynx -dump "http://$MATCH&quot; \
)| $SENDMAIL

[时代]如果您需要的是创建一个合适的MIME包,则会有各种MIME命令行实用程序,如metasend(用于交互式使用,因此对Procmail无法正常工作)和mpack可以尝试。 如果您的需求很简单,您甚至可以阅读MIME规范,并自行生成必要的标题和分隔符(回显Content-Type:multipart / mixed等等)。 相反,如果您的需求很复杂,请从CPAN获取Perl MIME包,并自行创建工具。 MIME FAQ(特别是第6部分)是寻找信息的好地方。 http://www.faqs.org/faqs/by-newsgroup/comp/comp.mail.mime.html

13.0简单Recipe示例

13.1保存:MH文件夹 - 编号消息

嗯。 这在procmail手册页中解释,但不是很好。 只有一到两次,手册页面告诉如何创建单个文件,而不是将消息连接到文件夹。 注意 /。 在文件夹名称的末尾

      :0
* condition
dir-folder/.

[手动]当传送到目录(或MH文件夹)时,您不需要使用lockfiles来防止几个并发运行的procmail程序搞乱。

在保存到目录中,procmail如何确定在$ MSGPREFIX之后放置什么来完成文件的名称?

[philip]以base-64编码的文件的inode编号与A-Za-z0-9-_字符串的顺序相反。 因此,例如,编号为59699的inode将被编码如下:

      59699 = 51 + 64 * ( 36 + 64 * 14 )
A=0, B=1, ..., N=13, O=14, ..., a=26, ..., k=36, ..., z=51,
0=52, ...
--> zkO

13.2保存:每月文件夹

      # Use any date method mentioned previously to define variables
# YYYY YY MM DD. Archive digests monthly

:0 c:
* ^From:.*\/mailing-list-digest@some.net
{
# Get the "mailing-list-digest" string, do not use following
#
# MBOX = `echo $MATCH | sed -e 's/@.*//' `
#
# Because we really don't need those extra shell processes.
# Procmail can derive the word 10x more efficiently

:0
* MATCH ?? ()\/[^@]+
{
MBOX = $MATCH
}

:0 :
$YYYY-$MM-$MBOX
}

13.3修改:过滤基础

注意每个Recipe中的 猫命令位置。

      :0 fbw
| echo "This is a line of text _before_ the body"; \
cat -

:0 fbw
| cat - ; \
echo "This is a line of text _after_ the body"

:0 fbw # prepend text before the body
| cat msg.txt -

:0 fbw # append text at the end of body
| cat - msg.txt

:0 fbwi # replace the body with text from file
| cat msg.txt

13.4修改:压缩消息体周围的空行

[david]取代身体的任何东西都需要外部进程,即使只是/ bin / echo。 为了从消息开始和消息结束处理空行,您可以做到这一点,如果整个身体符合 LINEBUF

      :0 fbw
* B ?? ^^$*\/.(.|$)*.$
| echo "$MATCH" # trailing extra newline intended

如果你的猫的版本是BSD-ish,

      # SysV's cat has a different meaning for -s and cannot do this

:0 fbw
* B ?? $$$
| cat -s

否则,可以使用非常简单的sed过滤器完成:

      :0 fbw
* B ?? ^^($)|$$$
| sed /./,/^$/!d

请注意,cat -s与其他结果略有不同:如果身体顶部有空行,cat -s将保留一个。 echo和sed建议将从顶部删除所有空行,像cat -s一样,保留在底部。

13.5修改:洗牌头总是相同的顺序

[phil]要将消息中的标题排序为可预测的顺序,可以使用以下配方。 在 -I和上述的论证之间,空格被消除了。 $ {variable:+ blah}的第二部分中的shell可能允许或可能不允许使用非引号的空格。 例如,在solaris 2.6下,/ bin / sh barfs on $ {FROM:+ - I“From:$ FROM”},而/ bin / ksh处理它很好。 我认为POSIX shell标准要求允许它,但是 下一个系统是否符合POSIX标准?

      :0
* ()\/^From: +\/.*
{
FROM = $MATCH
}

:0
* ()\/^Reply-To: +\/.*
{
RT = $MATCH
}

:0
* ()\/^X-Mailer: +\/.*
{
XM = $MATCH
}

:0
* ()\/^Message-Id: +\/.*
{
MID = $MATCH
}

:0
* ()\/^Date: +\/.*
{
DATE = $MATCH
}

:0
* ()\/^To: +\/.*
{
TT = $MATCH
}

:0
* ()\/^CC: +\/.*
{
CC = $MATCH
}

:0
* ()\/^Subject: +\/.*
{
SUBJ = $MATCH
}

:0 fh w
| $FORMAIL \
${XM:+-I"X-Mailer: $XM"} \
${TT:+-I"To: $TT"} \
${FROM:+-I"From: $FROM"} \
${RT:+-I"Reply-to: $RT"} \
${CC:+-I"Cc: $CC"} \
${MID:+-I"Message-Id: $MID"} \
${DATE:+-I"Date: $DATE"} \
${SUBJ:+-I"Subject: $SUBJ"}

13.6服务:自动应答消息

[elijah]这是响应空消息的一段代码。

      :0
* ! B ?? ...
| (echo "From: me@here.com" ; \
$FORMAIL -r -A"Precedence: junk" \
-A"X-Loop: me@here.com" ; \
echo "Your blank message was received.\n" \
"Did you mean to say something?\n" \
"\n" \
"-- \n" \
"My Signature\n" \
"this has been an automated response\n" \
) | $SENDMAIL

13.7服务:Ping响应者

有时我在路上,似乎没有访问我的消息的网站。 telnet连接失败,标准的Unix“ping”对我来说已经死了。 “该网站发生了什么?” 我在想。 这是我添加到我所有帐户的Recipe。 如果至少邮件主机已启动并提供一些状态信息,它将立即发送回复。

      :0
* ^Subject: ping$
{
:0 fh
| $FORMAIL -rt

# Remember, Don't send back anything that would be vital to
# attacker. It doesn't matter if the `uptime` or other
# scripts fail, the reply is sent anyway.

:0 c # Record this ping request
| ( cat -; \
echo `uptime`; \
echo "$HOST User count: " `who | wc -l`; \
) | $SENDMAIL

:0 : # or sink to $DEFAULT
$PING_SPOOL
}

13.8服务:简单的假期与procmail

不要忘记查看procmailex(5)手册页也有假期的例子。 以下提供的内容可能不适用于您。 这是一个非常简单的假期Recipe。 每当文件〜/ .vac存在时,都会调用假期程序。 确保你也有〜/ .vacation.msg文件准备好了。 记住, 假期不会 保存你的消息; 所以我们需要 c标志。

      #  Some prefer the non-dotted file which shows up in ls listing

vacationFlagFile = $HOME/.vac

:0 wc
*$ ? $IS_EXIST $vacationFlagFile
| vacation $LOGNAME

有些人喜欢在.procmailrc中引发一个标志,而不是创建一个文件。 如果你喜欢变量方法更好,这里是上述的等效实现

      VACATION = "yes"    # Comment this when not in vacation

:0 wc
* VACATION ?? yes
| vacation $LOGNAME

[philip][era]由于假期只发送回复 - 它从来没有发送原始#消息,一种方法来做两件事与你的.forward文件。 用你的登录名替换“abc”。

      |/usr/ucb/vacation","exec /usr/local/bin/procmail -f- ||exit 75 #abc

13.9服务:假期代码示例

[作者Eric Black eric@Mirador.COM ]这是procmail的一部分

      OFFSITE = "my_guest_login@wherever.I.am"

# Forward urgent mail to me at my off site address; afterward,
# continue processing it as normal The procmail pattern match
# may be case-insensitive, in which case this rule could be
# simplified...

:0 c
* ^Subject: .*urgent
| $SENDMAIL $OFFSITE


# Use "vacation" to tell other people I'm not here To enable,
# un-comment the next two lines; to disable, comment them out
#
# The -a Identifies another name that can legitimately
# appear in the To: line of the mail header instead
# of your login name

:0 wc
| vacation -a ericb eric

这里〜〜.vacation.msg文件

      Subject: I'm out of town for a while
From: eric (via the vacation program)

I'm out of town until <return-date>. Your mail regarding
"$SUBJECT"
will be read when I return, or possibly at some unknown
time before then if I get a chance to check for mail.

If your message must be seen by me before I return,
you can send it with the word "URGENT" in the subject header.
Such mail will be automatically forwarded to me so that
I see it sooner.
--Eric

13.10服务:自动转发

[ timothy ]我有我的.procmailrc设置将邮件转发到另一个(仅邮件)帐户。 当我不会在帐户中时,我想转向转发

      #   look for the file to tell us whether or not to forward mail
# if the file exists, forward the mail
# or not

ELSWHERE = "me@elsewhere.com"
FILE = "$HOME/.forwardmail"

:0 c
*$ ? $IS_EXIST $FILE
! $ELSWHERE

# if a message arrives from the other account
# with the Subject 'forward-off' then remove the
# file, efectively turning off forwarding

:0 hwic
*$ ^From:.*$ELSWHERE
* ^Subject: forward-off
| $NICE mv -f $FILE $FILE.off

# if a message arrives from the other account
# with the Subject 'forward-on' then remove the
# file, efectively turning off forwarding on

:0 hwic
*$ ^From:.*$ELSWHERE
* ^Subject: forward-on
| $NICE mv -f $FILE.off $FILE

13.11服务:仅转发特定消息

这里是根据地址触发转发的代码片段。 如果你有很多这样的转发,你应该使用你要grep的简单的 awk数据库。

      #   By Jim Hribnak <EM>[email protected]</EM>
# info@domain1.com goes to joe@domain1.com
# info@domain2.com foes to fred@domain2.com

:0
* ^TO_()info@domain1.com\>
{
FORWARDTO = "$FORWARDTO joe@domain1.com"
}

:0
* ^TO_()info@domain2.com\>
{
FORWARDTO = "$FORWARDTO fred@domain2.com"
}

:0 fhw
* FORWARDTO ?? @
* ! ^$MYXLOOP
| $FORMAIL -A "$MYXLOOP"

:0 a
! $FORWARDTO

13.12服务:做消化

      # By <EM>[email protected]</EM>
# Add this message to the digest accumulator

:0 c:
| $FORMAIL -k -X From: -X Message-Id -X Date -X Subject >> $DIGEST

# Check size of digest, and send it off if it's big enough

:0
*$ -$DIGSIZE ^0
*$ `wc -l <$DIGEST` ^0
| $NICE send-digest $DIGEST

13.13杀死:杀死广告头和页脚

我最近订阅的邮件列表开始在每个通过列表(呻吟)的消息的开头和结尾添加一个“锅炉板”文本块。 文本总是相同的,并且始终处于消息的开头和结尾。

[david] sed可以同时做到这两个,但问题是,如果N> 0,那么sed从来不会知道从最后的N行; 它知道最后一行它读取它,但是当它看下一个最后一行,它不知道只有更多的一行。 然而,它确实知道它已经读取了多少行输入。

所以我有三个建议:如果你知道标题是X行长[这个例子就是5] ,并且页脚的第一行包含一些字符串或者模式,这些字符串或者模式不会发生在文章的重要部分,

      :0 fbwi
* conditions
| sed -ne 1,5d -e '/pattern/q' -e p

如果您确定要保留的最后一行的结尾,而不是要删除的第一行,请省略n选项和p指令:

      | sed -e 1,5d -e '/pattern/q'

最后,如果找到页脚的唯一可靠方法是从最后到达这么多行(因为任何搜索模式也可能发生在真实的文本中),我们可以按照你一直在做的得到数量最后一条重要线。 让我们说页脚长三行? 因为^。* $总是计数一行太多(长的故事),我们减去四个而不是三个:

      :0 fbwi
* conditions
* 1^1 B ?? ^.*$
* -4^0
| sed -e 1,5d -e "$="q

13.14杀死:用procmail简单杀死文件配方

杀戮文件在新闻阅读器中被广泛使用,可以在您输入新闻组时删除不感兴趣的帖子。 杀死文件通常每行包含一个单个条目以匹配消息内容,这可以通过procmail轻松完成。 但是请记住,对于每个消息procmail都会分配一个进程,因此在将消息文件规则应用到消息之前,请确保您的配方符合以下顺序:kill文件规则仅应用于 未知消息

      SINK MAILING-LISTS
SINK ANNOUNCEMENTS
SINK WORK MESSAGES
OTHER DELIVERIES
apply kill file rules and UBE recipes to the rest

如果其中一个头与kill文件中的一个模式匹配,那么配方将删除消息(即将其'传递')。

      :0 hW:  $HOME/.kill file$LOCKEXT
| egrep -i -f $HOME/.kill file

有明确的锁定文件的原因是您必须能够在您的procmail运行时更新kill文件。 下面给出了一个示例编辑脚本。

      #!/bin/sh
# program: kill file.sh
#
file=$HOME/.kill file
lock=$file.lock
cp $file $file.tmp
emacs -q $file # or use whatever you prefer: vi, pico
lockfile $lock
mv $file.tmp $file
rm -f $lock

13.15杀:重复信息

[Lars Kellogg-Stedman lars@bu.edu ]将此作为您的.procmailrc中的第一个条目,只要8K缓存未满,您将看不到任何重复项。 每周通过cron作业清除重复文件夹。 虽然可能很容易将重复的文件复制到/ dev / null,但我已经遇到了破坏的邮件客户端,所有邮件的 Message-id头中都有相同的值。

      :0
* ^Subject:\/.*
{
SUBJECT = $MATCH
}

MID_CACHE_LEN = 8192
MID_CACHE_FILE = $PMSRC/msgid.cache
MID_CACHE_LOCK = $PMSRC/msgid.cache$LOCKEXT

LOCKFILE = $MID_CACHE_LOCK

# IF the message has a message-id header
# AND formail -D is successful (exit status=0)
# THEN
# log a message to the procmail log
# sink the message

:0
* ^Message-Id:
* ? $FORMAIL -D $MID_CACHE_LEN $MID_CACHE_FILE
{
LOG="dupecheck: discarded message, $SUBJECT $NL"

:0 # Store duplicates, notice no lock!
duplicate.mbox
}

LOCKFILE # Release lock by killing variable

这里有一个简单的Recipe,一个略微修改的版本从[手册] 。 Procmail通知formail的成功,考虑到消息传递,并且不会因为c标志而停止处理rcfile,这让我们有一个信息落入安全复制收件箱。

      :0 hWc: $PMSRC/pm-msgid.cache$LOCKEXT
* ^Message-id:
| $FORMAIL -D 8192 $PMSRC/pm-msgid.cache

:0 a:
duplicate.mbox

1997年9月左右有一个非常重的线索关于重复检测,其中有一些有希望的东西被发布。 Eli的hashd <URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/procmail/ 1997-09 / msg00160.html>

Matt Saroff也开始了一个关于重复的线程:<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/procmail/ 1997-05 / msg00599.html>其中几个回复也是有帮助的。

13.16杀死:垃圾邮件过滤器与简单的Recipe

[Ed McGuire emcguire@i2.com ]看到几个垃圾邮件过滤器最近发布,从简单到复杂,我以为我也会分享我自己的。 我垃圾邮件来自我的ISP,但不是我的域名或我订阅的邮件列表之一。

      #   1.  mail to my domain
# 2. NOT addressed to me directly
# 3. NOT coming from mailing lists I'm subscribed to.

0:
* ^(received):.*psi\.com
* ! ^((apparently-)?to|cc):.*(i2|intellection)\.com
* ! ^(to|cc):.*(pdp-?8-lovers|procmail|sunshine|info-pdp11)
junk.ube.mbox

[Gordon Matzigkeit gord@m-tech.ab.ca ]我刚刚发现了一个有效的规则,将垃圾邮件与我的其他电子邮件分开。 只需将您的用户名替换为下面的行中的gord

      # Anything which is not addressed to me is probably SPAM.
:0:
* !^TO().*\<gord\>
junk.ube.mbox

这只能起作用,因为我处理我的.procmailrc之上的所有邮件列表地址(即从订阅的邮件列表到达其他文件夹的所有流量)。 大多数垃圾邮件客户似乎通过邮寄列表发送邮件,而不是创建巨大的用户列表

许多时候,sysadm安装发送垃圾邮件的知识地址列表,然后根据“黑名单”检查收到的邮件。 请记住,一些fgrep实现在-w字切换中有问题。 请注意,上述配方扫描FULL HEADER,因此请谨慎使用,即请注意添加到垃圾邮件域列表中。

      # by [philip]; egrep would do here too, if it is posix
# compliant, it may have -f switch that makes it behave
# like fgrep.
#
# Note: option -F would make [ef]grep to search fixed string
# instead of regexps.
#

BLOCK_FILE = $HOME/Mail/DeniedNames.lst
UBE_MBOX = $HOME/Mail/junk-ube.mbox

# To filter out the Subject lines, so that mails sent
# with the subject "Have you received a message from
# blah-blah@spam" don't get filtered.
# [era] suggested we use formail
#
# Edsel Adap <EM>[email protected]</EM> agrees there is a
# likely bug in Solaris 2.5.1 "/usr/bin/fgrep -i" and
# suggested the use of /usr/xpg4/bin/fgrep instead.
#
# <EM>[email protected]</EM> Sun Microsystems Developer Support
# Files in /usr/xpg4 are available via the SUNWxcu4 package,
# which is part of the user, developer, all, or Xall Solaris
# clusters.
#
# Solaris 2.4 doesn't have /usr/xpg4/bin/fgrep :-(, you
# must use `tr A-Z a-z' before piping the message to fgrep.

:0 hw:
*$ ? $FORMAIL -ISubject: |fgrep -i -f $BLOCK_FILE
$UBE_MBOX

文件DeniedNames.lst只是一个地址列表

      82338201@compuserve.com
Dwnliner@ix.netcom.com
Emerald@earthstar.com
FreeWay@dm1.com

13.17杀死:(un)订阅消息

我厌倦了某些“其他”邮件列表似乎传递到该列表的那些令人厌烦的(un)订阅消息,而不是像列表服务器那样捕获它们,就像SmartList一样。

[Adam Shostack adam@bwh.harvard.edu ]以下的帮助虽然往往太广泛了, (我使用.safe规则来覆盖这些情况)<1000是一个有用的hueristic。 取消订阅消息很久很少见。

      :0 :
* (Delete|u*n*Sub(s| )*| add | leave | help )
* < 1000
junk.misc.mbox

[Rodger Anderson <rodger@hpbs2245.boi.hp.com>]我一直在研究一个Recipe,从邮件列表中过滤掉那些不舒服的* bscribe和uns * bscribe消息,我发布了我迄今为止。 除此之外,它还会过滤出非常短的消息,我发现这些消息通常是列表所有者/请求地址的排序消息。

对于从(un)?s * bscribe开始的主题,我给予了很大的重视,对于包含这些单词的主题,它也非常重。 然后,我用这些话重新开始消息,并以较轻的重量从线开始。 然后,多次出现也会产生一些重量,直到一点。 然后我把所有消息中的单词反对。

      :0
* 1^0
* 30^0 H ?? ^Subject: +(un)?subscribe\>
* 20^0 H ?? ^Subject:.*\<(un)?subscribe\>
*$ 20^0 B ?? ^^$SPCNL*(un)?subscribe\>
*$ 10^0 B ?? ^$SPC*(un)?subscribe\>
* 8^.4 B ?? \\<(un)?subscribe\>
* -.4^1 B ?? \\<$a+\>
junk.misc.mbox

[Adam Shostack adam@bwh.harvard.edu ]如何寻找sub&unsub,以及一个常年拼写错误的“不合我”? 我也找到过滤添加,离开和帮助来有用。 这可能是在线上唯一的字。 我认为它与破坏的列表管理包有关。

      | :0
| * 1^0
| * 30^0 H ?? ^Subject: +(un)?subscribe\>

* 20^0 H ?? ^Subject: +(un)?sub?(scribe)?\>

(The B is often missing, as is the word fragment 'scribe')

| * 20^0 H ?? ^Subject:.*\<(un)?subscribe\>

* 20^0 H ?? ^Subject: +(add|leave|help)$

# fewer points if more words

* 15^0 H ?? ^Subject: +(add|leave|help)

[david 1998-10-20]你想要匹配消息,其中身体中的第一个非空白的东西是“取消订阅”在一行的最后,哪里有五行或更少的身体?

      :0
*$ B ?? ^^$SPCNL*unsubscribe$
* 7^0
* B ?? -1^1 ^.*$
junk.misc.mbox

^。* $总是计数一行太多,所以五行机构将被计为六; 这就是为什么我们需要偏见7,但是如果身体中的第一个非空白文本是单独的“取消订阅”一行,是一个行数真的有必要吗? 包含该单词的真实帖子将在一个句子的中间,如前一个。 通过指定行限制,您可以找到通过以前消息底部的长签名或附件的退订请求。

13.18时间:每天一次cron般的工作

[Bill Moseley moseley@netcom.com ]如果您只想每天做一次,那么您必须在某处存储日期,并检查该存储的日期。

      YYMMDD_FILE = $HOME/.yymmdd
YYMMDD = $YY-$MM-$DD

# Contains single line of procmail code
# YYMMDD_PREV = ..

INCLUDERC $YYMMDD_FILE

# If different date, then enter this block
# The echo updates stamp in file.

:0
*$ ! YYMMDD ?? ^^$YYMMDD_PREV^^
* ? echo "YYMMDD_PREV = $YYMMDD" > $YYMMDD_FILE
{
...do the cron jobs..
}

13.19时间:在给定时间运行Recipe

如果我把程序放在我的菜谱上,那么每次消息都会被执行。 这是一个问题,我不允许在此帐户中使用cron。 我正在寻找某种条件来检查当前时间,如果在晚上11点和上午7点之间的时间段执行该操作。

[david]你的From_行怎么样? 如果它们是sendmail和smail添加的传统类型,那么它们在收到时包括系统上的当地时间。 所以包括一个检查,小时是在07和22之间,如下所示:

      :0 c
* ^From .*some-address.* (0[789]|1.|2[012]):[0-5][0-9]:
| command

我包括分钟和分钟与秒钟的分隔,以便测试07-22范围的表达式只能在小时匹配。

13.20时间:触发邮件并使用cron

[david]在您的个人crontab中为您的userid(并不知道您是否特别cron“cd”到您的主目录首先)将以下条目:

      0 23 * * *        touch $HOME/.mail.relay.on
0 7 * * * rm -f $HOME/.mail.relay.on

如果你的cron不知道HOME变量(这是一个例外)

      0 23 * * *  /bin/csh -c 'touch ~LOGNAME/.mail.relay.on'
0 7 * * * /bin/csh -c 'rm -f ~LOGNAME/.mail.relay.on'

然后,在.procmailrc中做:

      :0 c
* ^From.*some-address
*$ $IS_FILE $HOME/.mail.relay.on
| command

只有当主体匹配并且文件测试成功时,脚本才会run_my_program。 文件测试只能在晚上11点到7点之间成功。

诚然,如果系统给出可用的From_行,我更喜欢以下建议。 我一直在使用它在给定的时间或日期打开和关闭procmail代码块,它的作品喜欢一个魅力。 它使用更少的进程,并且由于任何一个cron作业无法运行或不执行其任务的原因,不太可能得到状态错误。

这个页面只在白天

      :0 c
* ^From .*some-address.* (0[789]|1.|2[012]):[0-5][0-9]:
| command

这个页面在晚上

      :0 c
* ^From .*some-address.* (0[0-6]|23):[0-5][0-9]:
| command

13.21解码:Uudecode

[philip]这里是一些代码,当一些条件匹配时进行uudecode匹配。 这里的魔术字符串是“开始...文件”,然后将 身体馈送到 my_uudecode_program,无论它做了什么。

      :0 b
* ^From:.*someone@somewhere\.com
* ^Subject: Subject
* B ?? ^begin 644 file.tar.gz
| my_uudecode_program

13.22解码:MIME

      #   by Peter Galbraith <EM>galbraith@mixing.qc.dfo.ca</EM>
# MIME filtering of accented characters and split lines.
#
:0
* ^Content-Type: *text/plain
{
:0 fbw
* ^Content-Transfer-Encoding: *quoted-printable
| mimencode -u -q

:0 A fhw
| $FORMAIL -I "Content-Transfer-Encoding: 8bit"

:0 fbw
* ^Content-Transfer-Encoding: *base64
| mimencode -u -b

:0 A fhw
| $FORMAIL -I "Content-Transfer-Encoding: 8bit"
}


# 1995-10-18 Tim Pickett <EM>tbp@cs.monash.edu.au</EM>
#
# Decode MIME quoted-printable Content-Transfer-Encoding
#
# Conditions
#
# Mail has a MIME-Version header with a number in it.
# Header saying "Content-Transfer-Encoding: quoted-printable"
# exists

:0
*$ ^MIME-Version:$s*$d*(\.$d*)
*$ ^Content-Transfer-Encoding:$s*quoted-printable
{
:0 fhw # Remove header
| $FORMAIL -I"Content-Transfer-Encoding:"

:0 fbw # Decode the body.
| mmencode -u -q
}

13.23如何在邮件正文中发送命令

      :0 b
* ^Subject: ARCHIVE
| sed -e '/$s*[^a-zA-Z]/,$ d' | sh

13.24在一行上匹配两个单词,而不是一个单词

如何写一个方法来做到这一点:将邮件放在邮箱中,该邮箱具有两个字符串(一个和两个)的行,如下所示:

          one     two

但是将邮件保存在错误文件夹中,如果该行只作为第一个字符串,如:一个(字符串两个丢失)

[philip]我认为这些线将位于消息的正文中,而“一两之间的空格”你的意思是“一到二之间的空格”。 如果这些假设是错误的,那么您需要调整以下配方:

      # The 'B' tells procmail to look in the body instead of the header.
# The second colon tells procmail to lock the mailbox with a
# local lock file -- if mailbox is a directory then you don't need
# it. The brackets in the condition contain a space and a tab.

:0 :
*$ B ?? one$s*two
default.mbox

:0 :
* B ?? one
error.mbox

现在,即使“一”或“二”是另一个词的一部分(在“一”的情况下,在“两”的情况下)的开始时,上述也将匹配。 如果您不想要,那么您需要将配方更改为:

      :0 :
*$ B ?? ()\<one$s*two\>
default.mbox

:0 :
* B ?? ()\<one\>
error.mbox

13.25如何定义个人XX宏?

通过宏,我指的是可以在比赛中使用的procmail的FROM_DAEMON,TO和TO_。 这是自己制作宏的一种方式

[alan]定义HEADERS以包括您关心的那些标题。 选择以下定义之一(并删除或注释其他)。 这里有三种定义用户to_宏的方式

  1. 仅使用To:
  2. 使用To:或Cc:
  3. 至:,cc :,或显然为:

      to_ = '^To:(.*\<)?'
to_ = '^(To|Cc):(.*\<)?'
to_ = '^((Apparently-)?To|Cc):(.*\<)?'

你这样使用它

      :0 :
*$ $to_()foo@bar.com
address-matched.mbx

[jari]这里有更多的例子

      cc_      = "(^((Original-)?(Resent-)?(Cc|Bcc)):(.*[^a-zA-Z])?)"
from_ = "(^(Apparently-|Resent-)*\
(From|Reply-To|Sender):(.*\<)?|\
^From $NSPC+)"}

13.26如何通过身体匹配改变主体

假设您在正文中有匹配时更改邮件的主题。 预期的结果将是:

      From: foo@this.is
Subject: Fault: NNNN in program block YYY << changed

Fault: NNNN in program block YYY

这是答案

      :0 fhw
* ^Subject: NOK case report
*$ B ?? ^$s*\/Fault: [0-9a-f]+ in program block.*
| $FORMAIL -I "Subject: $MATCH"

13.27如何根据其他标题更改主题

假设您想要在邮件到达某个特定地址时更改主题; 或当某些其他头字段。 这是一种方法,我们假设邮件来到各种内部邮件地址。 请参阅上一节中的HEADERS宏。

      # By [alan]
# Examine headers, create a subject tag if we recognize a list

TAG = ""

:0
*$ ${HEADERS}info@foo.com
{
TAG = "info"
}

:0 E
*$ ${HEADERS}check@foo.com
{
TAG = "check"
}

# ...and so on...
# now, if TAG is set, insert it into the subject

MATCH # kill this

:0 fhw
* ! TAG ?? ^^^^
* ^Subject: *\/[^ ].*
| $FORMAIL -I "Subject: $TAG - ${MATCH:-<no subject>}"

或者您可以使用命令行参数,在.forward中添加以下行。 (别名文件语法)

      foo: "|/usr/local/bin/procmail -m /usr/local/etc/pm-tagit.rc foo"

然后在tagit.rc中,你会说:

      ARG = $1

:0
* ARG ?? ^^foo^^
{
TAG = "foo@go"
}

:0
* ARG ?? ^^somethingelse^^
{
TAG = "somethingelse@go"
}

即使有人Bcc:sa消息到foo@some.com,此方法也会工作。

13.28如何使用参数调用程序

...现在,假设我想用参数$ FOUND调用程序 ,并将结果返回RESULT,该怎么做?

存储在变量RESULT中的捕获的标准输出将被捕获。 还要考虑如果在$ FOUND的值中有空格或制表符应该会发生什么。 也许应该更好地包含引用。

      #   Make sure FOUND is not empty before passed to program

:0
* ! FOUND ?? ^^^^
{
RESULT = `program "$FOUND"`
}

14.0杂项Recipe

14.1匹配有效的Message-Id头

[philip]写了完整的符合RFC的匹配器。 按照链接

<URL: http : //www.xray.mpe.mpg.de/mailing-lists/procmail/1998-03 /msg00375.html>

      dq = '"'                                # (literal) double-quote
bw = "\\" # (literal) backwhack
ws = "[ ]*" # whitespace
atom = "[-!#-'*+/-9=?A-Z^-~]+"
word = "($atom|$dq([^$dq\]|$bw.)*$dq)'
local_part = "$word($ws\.$ws$word)*"
domain = "(\[$ws([^][\]|$bw.)*$ws\]|$atom($ws\.$ws$atom)*)"

:0
* ! $ ^Message-Id:$ws<EM>$ws$local_part$ws@$ws$domain$ws</EM>
thats-non-valid-message-id

14.2在消息中发送两个文件

如果您打算在邮件中发送多个文件,请确保每个文件最后都有多个空白行,以便它们可以一起使用。 而不是做

      (cat THIS; echo " "; cat THAT ) | $SENDMAIL

你做

      (cat THIS THAT ) | $SENDMAIL

但有时您无法控制文件,那么可以这样做,以确保有空白行。 注意,与首选相比,只使用两个进程。

      (echo '' | cat THIS - THAT ) | $SENDMAIL

[大卫]和一个sed专家会这样做

      (sed -e '$ !b' -e '/./G' -e "r THIS" THAT ) | $SENDMAIL
  • $:最后一行
  • !:除范围之外的所有地方(在这种情况下,除了最后一行之外的所有地方)
  • b:分支到一个标签。 没有标签:分支到最后(并且,因为-n没有效果,打印模式空间)

现在记住,除了最后一行之外,我们已经跳过了,所以其余的代码将只在输入的最后一行执行。

  • /./:在包含一个字符的行(但是我们只在最后一行到达这里,所以在最后一行如果它包含一个字符)
  • G:将一个换行符和保留空间的内容添加到模式空间(保持空间为空,所以基本上,如果最后一行已经为空,则不做任何操作,但是如果最后一行不为空,则附加换行符因此添加一条空白行)。
  • r文件:通过sed指令完成此操作后,读取命名文件并将其复制到输出。

sed的这一边只有在sed有几杯饮料后才出来

14.3过多引用消息

[1997年11月25日buck@Compact.COM]我管理LISTSERV邮件列表,我们的主持人要求我们减少以前发布的材料的多余报价。 ...主题:询问这是否过多引用。 以下的重量,这个额外的副本将激活所有身体线条的66%引用线。

[时代]我一定会忍受75%的报价。 最后,你们当然总是要面对那些宁愿改变引用风格的人来逃避这样的限制,而不是少报。 理想化的报价解析器也许应该意识到,在很多行上重现的非空白的前缀可能是一个自定义的引用字符串。

这将保留记者的原始主题(如果没有添加Re,则添加Re),因此模板文本应该指出问题的性质。

我不知道什么是适合生成行为更像我下面建议,任何一个接受者? 也许没有任何分数为空线,中和signatures(希望寄件人遵守“ - ”约定),并添加10 ^ 0.5每个引用的线和菜肴-15 ^ 0.3非引用? (我还没有真正探索过这个 - 可能完全是克里克)。[另外,也许长时间引用的材料应该比引用的片段更难处理 - 回复文本 - 引用片段 - 回复文本替代?]

      COPY_ADDRESS = "listAdm@foo.com"

:0
* ^Sender: <mailing list tag>
{
# - quoted lines
# - non-blank, non-quoted lines
# - completely blank lines

:0
*$ 10^1 B ?? ^$s*>
*$ -15^1 B ?? ^$s*[^>$WSPC]
*$ -15^1 B ?? ^$s*$
{
# You don't need to repeat the original condition here
# You also don't really need to extract SENDER
# Generate a reply with appropriate headers and the
# body quoted

:0 fhw
| $FORMAIL -rtk -A "Bcc: $COPY_ADDRESS"

# Now "replace" the body with template text + body (In
# other words, add the template before the quoted body)

:0 fbw
| cat $HOME/template.txt -

# Now send it off to recipients mentioned in generated
# header

! -t
}

# Wasn't excessively quoted; save it
:0 :
$SOME_MBOX

14.4发送消息到寻呼机块

我的寻呼机有200字符的限制。 但是,我有一个超过这个限制的冗长的联系人。 我想做的是将Recipe分成200字符(最大)消息的邮寄给我的寻呼机。

<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/ cgi-bin / w3glimpse2HTML / procmail / 1997-12 / msg00125.html?43#mfs>

[时代]关于转发到寻呼机的内容是这个列表中的重复的主题。 我试图找到一个很好的总结,所有的问题,但总是似乎有一些微小的扭曲,人们想要实现。 作为对后代的一般评论,Procmail部分通常是微不足道的,并且问题减少到编写一个好的程序(shell脚本或其他),以便按照您想要的方式精确地格式化文本,并将其分散在适当的块中。

这是将邮件正文分成更小的块,并在每个块上执行一个shell脚本。 折叠的-s选项表示如果可能,仅在空格上换行

      #   Create a duplicate of the message to forward to the pager.
# This will be reformatted and have most headers stripped off.

:0 c
{
# Construct header with only From: and Subject: retained

HEADER = `$FORMAIL -XFrom: -XSubject:`

# Reformat body as 200-character lines and send each
# as a separate message with the preconstructed minimal
# header

:0 bw
| tr '\012' ' ' | fold -s -w 200 | while read line; do
echo -e "$HEADER\n\n$line" | \
$SENDMAIL pageraddress@wherever.com ; done
}

如果您的回音版本不明白\ n表示换行符(和/或-e选项来启用此转义处理),则需要进行调整。 (你可能需要这么做 - 这大部分是未经测试的,在我有限的测试中,我发现这些消息将以或多或少的随机顺序到达,在脚本中插入暂停应该在一定程度上有所帮助,但可能会导致其他问题,不是一个理想的解决方案。)

我不知道是否需要标题修剪; 一些寻呼机网关似乎将报头作为消息的一部分进行计数,而其他的则不会。 再次,对于子孙后代,像这样的细节是相关的,当您询问如何做到这一点时。

消息到达时播放特定的声音

[Peter S Galbraith galbraith@mixing.qc.dfo.ca ]这是shell中的命令来产生声音:

      % cat anyfile | /usr/X11R6/bin/auplay /usr/lib/exmh/drip.au

但是,它不会直接在Recipe中工作

      procmail: Executing "/usr/X11R6/bin/auplay /usr/lib/exmh/drip.au"
Can't connect to audio server

奇怪。 如果我su用户邮件,该命令从shell工作。 无论如何,我通过完全指定音频服务器(这是我的工作站,我在哪里收到邮件)让它工作

      AU      = /usr/X11R6/bin/auplay
TUNE = /usr/lib/exmh/drip.au

:0 hwic
* ^From:.*foo@bar.com
| cat > /dev/null; $AU -audio tcp/mixing:8000 $TUNE

14.6组合多个Original-Cc和Original-To标题

如何使用procmail / formail将这些头文件中的信息合并到其CORRESPONDING标题中MINUS the Original- *请注意,我可以拥有多个Original-Cc:标题,并且我希望所有收件人合并成一个Cc:标题。

      #   1998-01 by [david]
# initialize as unset

ORIG_TO ORIG_CC

# The -c option to formail takes care of headers continued onto
# indented lines; the pipe to tr takes care of multiple
# Original-To: headers by linking their contents with commas.
:0
* ^Original-To:.*[^ ]
{
ORIG_TO = `$FORMAIL -zcxOriginal-To: | tr \\12 ,`
}

# Drop trailing comma from tr:
:0 A
* ORIG_TO ?? ,^^
* ORIG_TO ?? ^^\/.*[^,]
{
ORIG_TO = $MATCH
}

# Likewise for Original-Cc: lines:

:0
* ^Original-Cc:.*[^ ]
{
ORIG_CC = `$FORMAIL -zcxOriginal-Cc: | tr \\12 ,`
}

:0 A
* ORIG_CC ?? ,^^
* ORIG_CC ?? ^^\/.*[^,]
{
ORIG_CC = $MATCH
}

# Now, let's install the changes if needed:
# with -A instead of -I or -i it should
# not clobber existing To: or Cc: information.
# -A : Append a custom header field onto the header in any case.

:0
* ORIG_TO ?? ^^^^
* ORIG_CC ?? ^^^^
{ }
:0 E fhw
| $FORMAIL \
${ORIG_TO:+-A "To: $ORIG_TO"} \
${ORIG_CC:+-A "Cc: $ORIG_CC"}

14.7以加密格式转发敏感信息

Valdis.Kletnieks@vt.edu请注意,标准的Unix crypt(1)命令不安全,因为它使用了在二战期间由Benchley Park家伙(图灵和其他人)打破的谜引擎的修改,使用基于机械继电器的计算机。 因此,使用任何比Radio Shack TRS-80更重要的计算机,轻松破坏它。 在任何comp.sources.Unix档案中,他们在十年前发布了一个“Crypt Breaker's Workbench”。 由于类似的原因,我也不能推荐使用单程56位DES。 三重DES(具有有效的112位密钥)看起来安全,PGP提供的任何加密也是安全的。

      #   by [alan]
# See if addressed *directly* to me, and ..
# ..has not already been forwarded

KEY = "TheMagic"
FORWARD_EMAIL = "foo@bar.com"

:0
*$ ^To:.*$LOGNAME(@|[^0-9a-z]|$)
*$ ! ^$MYXLOOP
{
# now let's encrypt the body using mimencode

:0 fbw
| echo "MIME-Version: 1.0" ; \
echo "Content-Type: application/crypt" ; \
echo "Content-transfer-encoding: base64" ; \
echo "" ; \
crypt $KEY | mimencode -b

# Now let's prepare the headers for forwarding the mail,
# and mark it so we don't loop

:0 fhw
| $FORMAIL -I"Resent-To: $FORWARD_EMAIL" -I"$MYXLOOP"

:0
! $FORWARD_EMAIL

}

15.0 Procmail和PGP

15.1自动解密pgp消息

警告 :如果使用remailers或匿名服务,则必须使用不同的密码和不同的用户标识来解密传入的邮件。 如果您只收到使用一键加密的消息,那么您可能对您有用。 但是,通常认为将密码刻录到您的.procmailrc中是一个巨大的安全隐患。

      :0 fbw
* B ?? PGP ENCRYPTED MESSAGE
| pgp -z "your pass phrase" -f +batch 2>&1

15.2从密钥服务器获取密钥

      # by Adam Shostack <EM>adam@bwh.harvard.edu</EM> 1996-02
#
# This first ruleset protects me from mailbombs from an automated
# service that I often send incorrect commands to, generating 5mb
# of reply. It also sorts based on success of the command.
#
# swissnet.ai.mit.edu is fast key server

:0
* From bal@swissnet.ai.mit.edu
{
:0 h
* >10000
/dev/null

:0 h
*^Subject:.*no keys match
/dev/null

:0 E
| pgp +batchmode -fka
}

15.3自动抓住输入的pgp键

      #  [Opher Kahn <EM>kahn@dg-rtp.dg.com</EM>] This first ruleset protects
# me from mailbombs from an automated service that I often send
# incorrect commands to, generating 5mb of reply. It also sorts
# based on success of the command.
#
# swissnet.ai.mit.edu is PGP key server

:0
* From bal@swissnet.ai.mit.edu
{
:0 h
* >10000
/dev/null

:0 h
*^Subject:.*no keys match
/dev/null

:0 E
| pgp +batchmode -fka
}

# auto key retrieval
#
# I have an elm alias, pgp, points to a key server The log file
# gets unset briefly to keep the elm lines out of my log file.

:0 W
* B ?? -----BEGIN PGP
* H ! ?? ^FROM_DAEMON
{
KEYID = `/usr3/adam/bin/sender_unknown`
}

LOGFILE=

# #todo: We should get rid of the 'elm' dependency here.
# #todo: correct this sometime... [jari]
#

:0 ahc
* ! ^X-Loop: Adams autokey retrieval
| $FORMAIL -a"X-Loop: Adams autokey retrieval" | elm -s"mget $KEYID" pgp


#!/bin/sh
#
# Script: sender_unknown
#
# unknown returns a keyid, exits 1 if the key is known. $output
# is to get the exit status. Otherwise, this would be a one
# liner.

OUTPUT=`pgp -f +VERBOSE=0 +batchmode -o /dev/null`
echo $OUTPUT | egrep -s 'not found in file'
EV=$?
if [ $EV -eq 0 ]; then
echo $OUTPUT | awk '{print $6}'
fi
exit $EV

# end of sender_unknown

16.0包含使用

16.1使用:多个rc文件

...如果处理从包含的rc文件的末尾落下,INCLUDERC语句是否作为一种“调用”功能将控制权返回给“原始”rc文件? 或者如果处理结束,邮件是否会被送达到$ DEFAULT并处理停止? 假设我有这些命令

      INCLUDERC = $PMSRC/pm-a.rc
INCLUDERC = $PMSRC/pm-b.rc
INCLUDERC = $PMSRC/pm-c.rc

是的,该控件将返回到原始文件,其中includeerc被调用。 而不,邮件不会在$ DEFAULT中传递,因为includerc只是结束:处理继续,直到顶层没有更多的语句。

Includerc不仅仅是一个切片的顶级Recipe。

16.2使用:有条件地调用rc文件

过滤UBE时防止错误命中的一个有趣方法是尝试查看消息是否来自某个有效目的地。 如果它来了,那么它不应该通过UBE过滤器运行,因为它可以过滤有效的消息。 没有ube过滤器是完全防弹的。

这是一个例子,其中UBE检测只有当消息来自某个我不知道的地方(或者我刚刚忘记调整我的.procmailrc)时才会使用。

      ME      = "(me@here.is)"
LISTS = "(procmail|list-a|list-b)"

:0 # Idea by Bill Moseley
*$ ! ^TO_()$ME
*$ ! $LISTS
{
# Could be UBE or I might be on a unknown distribution list.
INCLUDERC = $PMSRC/pm-ubecheck.rc
}

[dan]那会工作; 然而,通常的做法是将列表中的邮件提交给Recipe(首先,根据Bill的偏好,头部中提到的procmail的任何内容都被视为与该列表中的邮件相同) 那么考虑的唯一剩余条件就是意外的盲卡:*! ^ TO_moseley。 如果您的垃圾邮件比合法邮件(包括从订阅列表中的邮件合法)得到的垃圾邮件多得多,并且您希望procmail立即处理垃圾邮件,则此方法很好。 我属于几个非常活跃的邮件列表,所以我实际上收到比垃圾邮件更多的合法邮件。

一个获得两个世界最好的方法是:

      *$ ! ()\/(^TO_$LOGNAME|procmail|list-(ABC|123|XYZ))

因为那时,如果正则表达式匹配(因此否定条件失败,并且不绕行到$ PMSRC / checkspam.rc),则MATCH已经设置为邮件列表的名称,您可以通过检查进行进一步的测试MATCH(或您将其复制到的变量),而不是重复完整的头部搜索。 [我更喜欢使用变量$ LOGNAME而不是硬编码我的名字,因为其他人可以使用代码,我可以在我的日志名不同的网站上使用它,如果我的日志名称被更改,我的procmailrc将跟上例如(我已经分开了
条件成两行,这样,根据Bill的偏好,头文件中提到的procmail将会收到Procmail列表文件夹中的消息,即使$ ^ TO_ $ LOGNAME的匹配也存在并且出现得更早):

      :0
* ! ()\/(procmail|list-(ABC|123|XYZ))
*$ ! ^TO_$LOGNAME
{
INCLUDERC=$PMSRC/pm-ubecheck.rc
}

# The next recipe has an `E' flag, so it will be examined
# only if the preceding one didn't match; thus if $MATCH was
# set inside pm-ubecheck.rc, it won't hurt anything here, and a
# value for $MATCH set in pm-ubecheck.rc
# won't be mistaken for a list name:

:0 E: # MATCH is non-null only if it matched a list name
* MATCH ?? (.)
$MATCH

# Remaining recipes will be read only for two types of mail:
# those that met $^TO_$LOGNAME but not any expected list
# name, and those that went through pm-ubecheck.rc but came out
# undelivered.

16.3使用:自动加载rc文件

现在当你知道includeerc可以有条件地调用时,让我们讨论一下“自动加载模块”。 例如,您可能会看到导入预定义变量的以下语句模块:

      :0
* ! WSPC ?? ( )
{
INCLUDERC = $PMSRC/pm-javar.rc
}

它说“如果变量WSPC不包含空格,那么加载模块”。 如果模块已经被其他rc文件加载,那么WSPC将会存在。 如果还不存在,则模块被加载。 这是有条件地将功能或变量加载到当前模块的典型示例:

      Check if feature is present, No? Then load module module.

贾斯汀·劳埃德jlloyd@harris.com建议缓存所包含的rc文件的一般方式。 使用记录每个包含的模块的顶级脚本。 该模块仅在尚未包含的情况下加载:

      #   pm-xximport.rc

:0
* ! INCLUDE_CACHE ?? ()\<$RC\>
{
# Module was not there yet, add it to the list
INCLUDE_CACHE = "$INCLUDE_CACHE$RCFILE$NL"
INCLUDERC = $RC
}

这是不同的方法,然后是前一个。 而不是检查功能,检查模块的锁定。 可以用于同一件事的硬币的两边。 你可以选择任一解决方案,但这里有一些想法:

  • 添加额外的顶级INCLUDE_CACHE是额外的工作。 Procmail必须每次打开单独的顶级rc文件

      RC="pm-xxscript.rc"   INCLUDERC=pm-xximport.rc
  • 如果功能已经存在,您仍然必须打开pm-xximport.rc文件,以便每次调用才能找到它。 例如 这里你pm-xximport.rc被称为3次,无论是1,2,3已经存在

      RC="pm-xxscript1.rc"   INCLUDERC=pm-xximport.rc
RC="pm-xxscript2.rc" INCLUDERC=pm-xximport.rc
RC="pm-xxscript3.rc" INCLUDERC=pm-xximport.rc

通过以前的简单功能测试,procmail可以对现场进行评估,而无需打开单独的文件:

      if no feature present..
then load

if no feature present..
then load

但是请注意,两个建议都是一样的; 实施只是不同。 如果每个模块包含RC文件的典型数量足够大,我会用Justin的方式。 通常它几乎没有,说一两个,其目的是定义获取日期信息的变量。

16.4制作:命名rc文件

当你写一个rc文件,想想它是否可以被泛化,以便别人可以使用它。 您可以采用所有procmail文件以前缀 pm开头的样式,以便它们可以与同一目录中的其他文件堆叠。 如果你简单地命名为 rc。* ,看看会发生什么:

      % ls rc*        # fine, print rc files

但是如果要打印所有procmail相关的文件并使用一个命令进行备份,则起始前缀更好:

      % ls pm-*

--> pm-mytest.rc
pm-jaube.rc
pm-tips.txt
pm-art.txt
pm-incoming.log
pm-list.mbox # the mailing list

名称foramt可以是rc文件的pm-xxSCRIPT-NAME.rc ,其中xx是名字和姓氏的首字母,如(J)ohn(D)oe。 这些脚本是可以分发的产品版本。 通常也有私人脚本来处理其他的东西,比如邮件列表,工作信息等等。 他们会有一个前缀我的 。

      pm-jdscript.rc
pm-myscript.rc << private version

当下载别人的脚本时,如果它的名字是独一无二的根据谁做的:

      pm-ajscript.rc      # Average Joe's script.

16.5制作:在保存procmail变量时使用名称空间

如果要编写与任何其他编程语言子程序一样的rc文件,则必须将其与世界分开,并使其运行良好。 一个子例程传统上是一个黑盒子:你用参数来调用它,并用返回的值进行响应。 你不需要知道那里发生了什么。 而且你期望子程序没有改变现有环境,比如procmail变量 DEFAULT LOGFILE等结束。

所以一个好的RC子程序的过程图是:

                          pm-xxscript1.rc
call --> +------------+
arguments | black | --> it may call
| box | other subroutines
| | <-- pm-xxscript2.rc
output values <-- +------------+

Procmail没有本地变量,所以您必须将变量放在全局名称空间中。 让我们看一个例子,子程序使用MAILDIR作为chdir目的。

      MAILDIR_xxscript1   = $MAILDIR              # save
...
MAILDIR = new location
...
...at the end of subroutine
MAILDIR = $MAILDIR_xxscript1 # restore

此时子程序启动时保存原始值,并在子程序退出时恢复原始值。 所使用的全局命名空间(xxscript1)是唯一的,并且保证不会与其他人发生冲突。 如果pm-xxscript2.rc也将使用MAILDIR ,则保存的值将被存入

      PROCMAILVAR_xxscript2

而且两者不会混在一起MAILDIR 。 因此,保存变量的通用名称为:

      PROCMAILVAR_scriptname

这是遵循简单的“洋葱”或“”模型,其中变量的值在更改之前被保存并在出口点恢复。

      save-x-1
set--x-1

save-x-2
set--x-2
..
restore-x-2

restore-x-1

16.6制作:rc文件中的公共和私有变量

如上所述,变量应放在RC文件的名称空间中。 用户界面变量(public)应为全部大写,私有变量应以小写字母开头。 您是否使用“theVarStyle”或“the_var_style”取决于您。

      [script pm-xxscript.rc]

# ........................... public

XX_SCRIPT_FLAG = ${XX_SCRIPT_FLAG:-"default"}
XX_SCRIPT_VAR = ${XX_SCRIPT_VAR:-"default"}

# ........................... private

charset = "a-z1-2"
regexp = "something-that-matches"

您是否需要将前缀xx_script粘贴到私有变量中取决于您是否调用另一个可能与您使用相同名称的includerc

      [pm-xxscript.rc]
charset = ... # watch this
...
INCLUDERC = .. # call another subroutine

charset = .. # holy cow, it used same variable

..back in the pm-script.rc

:0
* $charset # BOOM, not what you think.

在这种情况下,这将是明智的:a)不要在文件的顶部定义字符集 ,而是将定义移动到使用它的配方之前,或者b)使用xxScriptCharset命名唯一的名称。

16.7构建通用rc文件的经验法则

  • 在文件开头编写好的文档:如何设置includerc并解释它的作用。 如果您不包含文档,人们可能会跳过您非凡的有用脚本。 此外,请记住,脚本存在于网络中,并在断开连接后经过很多手。
  • 保持这样的布局:用户界面变量必须全部以大写字母表示。 熟悉(1)标签。 请注意第一行和最后一行:如果保持格式,则任何通用工具都可以从任何文件(或邮件)中删除代码,因为它由“pm-xxScript.rc”和“pm”结尾分隔-xxScript.rc“。 请参阅Unix(第一行)的第一行语法。

          # pm-xxScript.rc -- procmail script for ...
# DOCS

USER VARIABLES

private variables

CODE

# end of pm-xxScript.rc
  • 始终在某个地方包含版本号或最后修改日期。 喜欢一些版本控制工具,如RCS,VCS,ClearCase,无论您手头上有什么。
  • 在适当的地方使用虚拟变量名来告诉代码中发生了什么。 请记住,如果您无法通过查看代码执行的地球上的LOG来告诉您, VERBOSE设置没有多大帮助。

          dummy = "start of pm-xxScript.rc"
...
dummy = "Now testing if we have control message XXX"
:0
* condition
{
dummy = "Now testing if the command is YYY"
:0
* condition
...
}
...
dummy = "end of pm-xxScript.rc"
  • 如果您需要某些常用头文件的值,请不要像这样调用formail,因为该值可能已经在您的includerc之前可用了。 例如,用户可能已经需要主题值并将其存储在变量中

          [in pm-xxScript.rc]

XX_SCRIPT_SUBJECT = `$FORMAIL -xSubject:'

[User may have already read the content to SUBJECT]

SUBJECT = `$FORMAIL -xSubject:'
INCLUDERC = $PMSRC/pm-xxScript.rc

Your pm-xxScript.rc launches an unnecessary formail call. Instead,
use the existing SUBJECT.

[user]
:0
* ^Subject:\/.*
{
SUBJECT = $MATCH
}

...

XX_SCRIPT_SUBJECT = $SUBJECT # Note this!
INCLUDERC = $PMSRC/pm-xxScript.rc

[ in the pm-xxScript.rc variable definitions ]

# User should initialize the variable
# XX_SCRIPT_SUBJECT if he already has read the
# subject.

:0
* XX_SCRIPT_SUBJECT ?? ^^^^
* ^subject:\/.*
{
SUBJECT = $MATCH
}
...the rest of the code
  • 如果发送自动回复,则添加标题X-Loop并对其进行测试。 X-loop防止响应已经响应的消息。

          :0
* condition
* ! ^FROM_DAEMON
*$ ! ^$MYXLOOP
{
# Ok, now we're clear to send an automated reply
}

16.8一个包含骨架

这是我在我的所有模块中使用的includerc文件框架。 有趣的“$”是为text2HTML Perl过滤器。 文档部分可以很容易地被翻译成HTML,只需保留标准的4个选项卡列位置,并用“文件ID”开始描述,并用“更改日志”结束。 制作HTML的命令是:

      % ripdoc.pl pm-xxscript.rc | t2HTML.pl > pm-xxscript.html

这两个perl文件可以从我的ftp目录中获得。

      # pm-xxscript.rc -- one line description string here
# <EM><STRONG>$Id: pm-tips.txt,v 2.28 2004/10/06 13:55:39 jaalto Exp $</STRONG></EM>
#
# File id
#
# .Copyright (C) 1997-98 Foo Bar
# .$Created: YYYY-MM $
# .$keywords: procmail [subroutine|recipe] whatItDoes $
#
# This code is free software in terms of GNU Gen. pub. Lic. v2 or later
# You can get newest version by sending mail to maintainer with
# subject "send <FILENAME>"
#
# Description
#
# This subroutine Parses <what> from variable INPUT
#
# Required settings
#
# PMSRC must point to source directory of procmail code.
# This subroutine will include
#
# o pm-xxScriptA.rc
# o pm-xxScriptB.rc
#
# Call arguments (variables to set before calling)
#
# o INPUT, the string from where to parse...
# o VAR1, description, default is ...
# o VAR2, description, default is ...
#
# Returned values
#
# ERROR will have value "yes" if couldn't parse INPUT
# OUTPUT will have result after successful parse
#
# Example usage
#
# :0
# * condition\/.*
# {
# INPUT = $MATCH
# INCLUDERC = $PMSRC/pm-xxscript.rc
# # OUTPUT has the result
# }
#
# Change Log: (none)

# ..................................................... &init ...

dummy = "init: pm-xxscript.rc start"

# Read the standard variable definitions if they are not
# yet defined: that's "if WSPC variable does not contains space,
# as it should, then global variables haven't been read yet"

:0
* ! WSPC ?? ( )
{
INCLUDERC = $PMSRC/pm-javar.rc
}

# .................................................... &input ...
# - User configurable variables with reasonable defaults
# - But parameters like "INPUT" that must be set beforehand
# are not mentioned here.

VAR1 = $VAR1{VAR1:-"default1"}
VAR2 = $VAR2{VAR2:-"default2"}

# .................................................... &do-it ...

dummy = "subroutine: pm-xxscript.rc parses now that and that"

<the code>

dummy = "subroutine: pm-xxscript.rc end."

# end of pm-xxscript.rc

17.0邮件列表服务器

      Note: These examples are for ad-hoc lists. Procmail language is not
suitable for handling complex mailing list administration
although there is Procmail based MLM called *Smartlist*. The de
facto MLM software with web based interface is nowadays Python
based GNU *Mailman*.

简单的邮件列表服务器

      # by Lars Hecking <EM>lhecking@nmrc.ucc.ie</EM>
#

MAJORDOM = "majordomo-(users|docs|workers)"

:0 w
*$ ^(Sender|To|Cc):.*\/$MAJORDOM
*$ MAJORDOM ?? ()\/$\MATCH
| $APPNMAIL $LISTS/$MATCH

这是另一个,由Brock Rozen brozen@torah.org提供来自[dan]

      # get the date in RFC822 format for insertion into some messages;
# the "Resent-Date:" field is copied from the "Date:" field on
# some systems. RFC1123 says "All mail software SHOULD use 4-digit
# years in dates..."

LIST_NAME = "myList"
LIST_ADDR = "$LSIT_NAME foo@bar.com"
LIST_DATE = `date '+%a, %d %h %Y %H:%M:%S %Z'`
LIST_ERR = "$EMAIL" # my admin address

# Sendmail ignores "To:" in the presence of "Resent-To:"
#

:0 fhw
*$ !^X-List: $LIST_NAME
*$ ^TO()$LIST_NAME
| $FORMAIL
-A "X-List: $LIST_NAME" \
-I "Resent-To: $LIST_ADDR " \
-i "Resent-Date: $LIST_DATE" \
-I "Errors-To: $LIST_ERR" \
-A "Precedence: bulk" \
-A "X-Loop: $COMSAT"

:0 a
! -oi `cat /var/tmp/src/power-users.list`

18.0常见问题

18.1 Procmail模式:正常,发货和邮件过滤。

a)如果系统上没有/ etc / procmailrc,那么procmail的配方是什么?b)如何决定地址/本地部分是否有效c)procmail如何选择邮箱放弃邮件

[philip]使用-d标志调用传递模式。 所有参数是-d是用户名。 它通常被MTA用于向用户发送邮件,而且如果给定无效的用户名,则procmail将返回失败。 在交付模式下,procmail在用户的.procmailrc之前读取/ etc / procmailrc。

注意 :Procmail只有在setuid root的情况下工作,如果使用-d命名的收件人的ruid调用,或者在构建例程确定它是安全的某些操作系统下,如果euid是收件人和egid是收件人的登录组。

使用-m标志调用Mailfilter模式。 它只接受一个rcfile作为参数 - 其他参数可以是变量赋值,也可以是rcfile本身可用的参数,如$ 1,$ 2等。如果指定的rcfile位于/ etc / procmailrcs /下,那么procmail将会在该文件的所有者的uid上。 否则,它将作为调用它的用户运行。 / etc / procmailrc,procmail -d读取,被忽略。 在邮件过滤器模式下,procmail取消了ORGMAIL和DEFAULT禁止正常传送 - 到达rcfile的结尾导致邮件退回。 如果rcfile设置其中的任何一个,则procmail将尝试传递到该邮箱,如果它脱离rcfile的末尾; 但是,邮箱将必须由proidail运行的uid / user写入。

注意 :在命令行中只能命名一个rcfile,但可以在位置参数中传递其他rcfiles的名称,以便稍后在INCLUDERC分配中使用。

通常不使用-m或-d标志来调用正常模式。 它接受任何数量的rcfiles和变量赋值作为参数。 Procmail在此模式下作为调用用户运行。 / etc / procmailrc被忽略。

所以,回答你的问题:如果procmail到达指定的rcfile结尾,它会弹出邮件(/ etc / procmailrc被忽略)。 一切都取决于rcfile - 如何确定地址是否有效,以及放置消息的位置。

18.2 Procmail作为sendmail Mlocal邮件过滤设备

...我是我公司的一个新的系统管理员,我一直在尝试设置Procmail作为邮件过滤设备(仍然使用邮件作为Mlocal)我已经尝试设置sendmail.cf使用Procmail作为过滤器(我们想使用当前的邮件程序作为本地邮件程序)与一个本地procmail rc文件。 Procmail似乎工作正常,如果设置为本地邮件程序,但我仍然无法将其设置为过滤器。

[John M Vinopal banshee@abattoir.com answer sendmail.cf]

      R$+ < @ $=a . > $*
$#procmail $@ /etc/mail/procmailrc $: $1 < @ procmail > $3
R$+ <@ procmail > $* $1 < @ resort.com .> $2

所以它通过procmail发送foo@resort.com的任何形式,并将其重写为foo @ procmail。 procmail脚本重新注册它,它绕过procmail的调用,然后被重写回foo@resort.com。

      /etc/mail/procmailrc:
:0
! -oi -f "$@"

18.3 Procmail不会通过8位字符

你错了 Procmail不会对您的邮件做到这一点。 Frank Gadegast phade@powerweb.de告诉你:
  • procmail没有问题,是sendmail
  • 我在sendmail.cf中取消了这一行,现在我得到了所有好的德国Umlauts。

          # strip message body to 7 bits on input?
# O SevenBitInput

问题是一些电子邮件通过本地邮件程序procmail运行,并全部到达(本地邮件),所有来自外部的邮件(丢到我使用过procmail过滤器的最常用的邮箱)都没有到达。 这让我认为它是procmail,但这些邮件来自外部,这是sendmail的责任。

18.4我的ISP对安装procmail不太感兴趣

...我最近要求我的ISP安装procmail,他们回答说不。 他们的主要原因是他们不希望招致任何/所有订户设置邮件列表的流量。

[Jon Lewis <jlewis@inorganic5.chem.ufl.edu>]您不需要对/ etc / aliases或/ etc / procmailrc的写入权限来设置邮件列表吗? 告诉ISP,procmail将大大提高邮件传递,并使所有用户能够过滤掉垃圾邮件,而不会看到它。 如果他们仍然拒绝,找一个更好的ISP。

18.5我的ISP有系统的procmailrc; 这是一个好主意吗?

[eli]我,一个,不喜欢我的ISP将东西放在/ etc / procmailrc中。 有一些珍贵的一点,我会从中获益,并有很多机会让他们犯错,我不会有。 在一个ISP,我知道人们对某些sendmail级别的邮件过滤感到不安。 其中一个令人不快的是一个习惯性的投诉垃圾邮件发送者的ISP人员。 如果他们真的在那里,他不希望出现问题。 另一个人根本不信任过滤。

编写一个shell脚本,它将给用户一个.procmailrc,其中包含一个系统范围共享的procmailrc是最好的方法。 这迫使过滤成为“选择加入”。

18.6 Procmail更改邮箱和目录权限

作者:Ed McGuire emcguire@i2.com 。 在使用procmail之前:

      > -rw-rw----   1 foo      mail  1127 Sep 11 07:33 foo

后:

      > -rw-------   1 foo      mail  1517 Sep 11 07:34 foo

当UMASK环境变量比邮箱的模式更加限制时,procmail会更改邮箱的模式。 UMASK的默认值为077.如果要保留对邮箱的组访问权限,我认为您可以在rcfile中将UMASK设置为007:

      UMASK = 007

进一步注意:上述UMASK在.procmailrc中的建议不起作用。 见GjermundSérsethgjermund@nextel.no的评论

然而,在procmail甚至打开.procmailrc之前处理了DEFAULT的权限,因此更改umask将不会对邮件反应器产生任何影响。

[Scott J. Kramer sjk@lux.com ]在procmail(1)手册页的杂项中有记录:

如果/ var / mail / $ LOGNAME已经是一个有效的邮箱,但是对它的权限过于宽松,那么procmail会更正这个。 为了防止procmail这样做,请确保u + x位被设置。

否则,您可能会注意到syslog消息,如:

procmail:对“/ var / mail / sjk”执行更严格的权限

当chmod的文件为600时。如您所见,这与SYSV(Solaris 2反正)默认邮箱保护为660,gid = 6(邮件)不一致。 我认为这是一个操作系统相关的错误,使用“chmod u + x ...”作为解决方法。

18.7在编译期间将mbox权限更改为660

...看起来,procmail的邮件返回到假脱机,它正在用owner.group user.mail和权限600写出来。对我来说这是合理的。 邮件由/ bin / mail发送到线程的所有者用户,组邮件660。

当procmail递送邮件时,稍后尝试从.forward文件中删除procmail的传递失败:/ bin / mail没有权限(或拒绝使用其权限)。

由于我们有灵活和不守规矩的用户,他们将前进进出,这是一个问题。

是否正确的解决方案强制procmail写660? 如果是这样,怎么办? 我假设在config.h的部分正好在警告之下,只是搞砸了一个部分,如果你认为你知道你在做什么。 我不喜欢我没有足够的知道我在做什么来走进那个领土,没有一点指导。

[alan]我曾经是加州大学圣巴巴拉分校工程学院的系统支持经理。

我们支持两台HP 9000 G30的大约1500位用户,使用其中一台作为集中式邮件程序。 邮件可通过NFS导出/ usr / spool / mail到超过200个工作站,各种类型:SGI,HP,Sun等

我们用procmail替换/ bin / mail作为本地邮件程序(Mlocal),因为procmail正确地避免了NFS锁定问题,并支持用户可配置的邮件过滤,而不会影响系统的安全性。

在改变之后的两年之内,由于procmail被用作本地邮件程序,我们没有丢失邮件。 如果您希望从当前的系统管理员进一步评论,请发邮件至“postmaster@eci.ucsb.edu”。

回答你的具体问题:

*您可以直接配置权限,通过更改config.h中的以下定义之一:

      /* bit set on mailboxes when mail arrived */
#define UPDATE_MASK S_IXOTH
/* if found set */
#define OVERRIDE_MASK (S_IXUSR|S_ISUID|S_ISGID|S_ISVTX)
/* the permissions on the mailbox will be left untouched */
#define INIT_UMASK (S_IRWXG|S_IRWXO) /* == 077 */
#define GROUPW_UMASK (INIT_UMASK&~S_IRWXG) /* == 007 */

然而,我们没有发现有必要:

  • 除了点锁定,我们禁止所有锁定,因为内核锁是NFS锁定问题的根源。 继续偶尔出现锁定问题,但这些是由受害者引起的使用不受支持和不鼓励邮件的邮件引起的问题,例如来自较旧的太阳的“邮箱”。 这些锁定问题与邮件传递无关,而是从邮件客户端使用内核咨询锁,然后将其清空,或者将其全部锁定。
  • 让用户使用.forward文件的另一种方法是创建一个希望使用procmail作为本地传递代理的用户的文件,并使用该文件初始化一个类变量。

在sendmail.cf中写一个特殊规则,当目标用户在特殊的procmail用户类中时,它使用Mprocmail而不是Mlocal传递邮件。

这使得尽管管理担心,想要procmail直接传递的用户。

在将Mlocal更改为使用procmail之前,我将其设置为在我们的系统上测试procmail传递。 我们在procmail类文件中放置了一些“志愿者”用户,他们没有任何问题(我是其中之一)。

18.8 .forward文件必须是真实文件

http://www.math.fu-berlin.de/~guckes/mail/forwarding.html

...我试图将一个软链接到〜/ .forward,但是我的procmail不会运行。 当我做了一个真实的〜/ .forward文件,然后它再次工作。 我的问题是 - 为什么procmail会将文件的链接视为与实际文件本身的不同之处?

      ln -s ~/.procmail/forward ~/.forward

[Werner Reisberger wr@tribe.ping.de ]这不是procmail的问题,这是一个MTA问题。 由于安全性原因,sendmail将不会将邮件传递到该文件。

[david] procmail对rcfile允许的权限有限制。 例如(我只是在这里猜测),它可以判断是否可以读取目标文件,但是无法判断谁可以写入它。 这防止了主要的安全漏洞

您可以将硬链接到该文件,因为硬链接与原始文件完全不可区分。 但请注意:与两个或多个名称链接的文件与仅具有一个(硬)链接的文件非常区别,例如,procmail将不会传递到具有两个或多个硬链接的普通文件夹。

您也可以将真实文件放在〜/ .forward中,并将〜/ .procmail / forward作为符号链接

[<mikk0022@maroon.tc.umn.edu>]我想,procmail的文件夹策略背后的原因是procmail以name而不是inode锁定文件。 因此,不能保证访问具有多个名称的文件的互斥。

我对.forward策略的理解是,符号链接不需要共享其目标的权限。 因此,有人的.forward符号链接可以具有适当的权限,而其目标可以被其他人写入。 这将允许具有写权限的任何人从用户的转发文件执行任何程序(潜在地)。

两个硬链接共享相同的权限,所以这个参数不成立。

18.9如果procmail已经是LDA,使用.forward

[Elie Rosenblum fnord@jurai.net ]如果你有一个.forward,它被sendmail用来替换相关用户对LDA的调用。 所以如果你有一个没有调用procmail的.forward,procmail是...

[david] Elie把答案带给了我一个名单,但是从阅读我的个人副本以来,我的收件箱已经被丢弃了。 在撰写本文时,列表副本尚未到达我,但是该句子的其余部分(正如我在读取之前所记得的那样)才是这样的,因为procmail在接收到的邮件中根本就不会被调用; a.forward优先于LDA。 那个情况从来没有发生过。 谢谢你的解释。

[Philip]抓住关于/ etc / procmailrcs / $ LOGNAME的一点。 您正在将procmail -d与procmail -m进行混合。

啊,得到它...在重新阅读手册页后。 关于/ etc / procmailrcs的部分真的只能在procmail是setuid root的时候才可以应用,所以再一次我没有经验,也没有完全遵循或保留。 所以/ etc / procmailrcs中没有任何文件被隐式使用,但是/ etc / procmailrc可以。

[Philip] $ HOME / .forward由sendmail处理。 如果你有一个转发,那么sendmail会重写尝试交付给你
尝试传递到.forward文件中列出的地址。

或者换句话说,.forward优先于LDA。 谢谢你们俩。

如果写入失败,则应将邮件放入邮件队列中

...我们要直接发送到用户的主目录。 但这当然可以暂时充满。 然后邮件不应该反弹,而是放回邮件队列,再试一次,直到它成功或者sendmail在5天后反弹(像往常一样)。 README文件说这是我的选择(反弹或不反弹),但是我找不到任何可以设置的地方。 设置此行为的正确位置是什么?

[1998-06-24 PM-L phil] -t标志使procmail返回EX_TEMPFAIL,通常它将返回EX_CANTCREAT。 如果您已将procmail作为本地传递代理,那么您应该在-d标志之前添加-t到A = define。

18.11 Qmail:如何使它与procmail一起工作

[1998-11-10 PM-L John Conover conover@inow.com ]你所做的就是快速安装和点转,(它们是可选的,不是必需的)然后cp / var / qmail / boot / proc或/ var / qmail / boot / proc + df,到/ var / qmail / rc。

[1998-11-10 PM-L Greg Boes gboes@ashfordtech.com ]从qmail常见问题(4.4如何使用procmail与qmail?)Put

      | preline procmail

进〜〜.qmail。 您将不得不使用procmail的完整路径,除非系统启动PATH中有procmail。 请注意,默认情况下,procmail将尝试传递到/ var / spool / mail / $ USER; 要改变这一点,请参阅INSTALL.mbox。

18.12 Qmail:Procmail仅显示/ var / spool / mail中的文件

... Procmail似乎想在/ var / spool / mail中做某事。 但是,由于我使用qmail,我没有/ var / spool / mail。 有没有办法让procmail不在那里创建临时的东西?

[philip]获取procmail 3.11pre7并取消注释,并正确的本地设置MAILSPOOLHOME =“/。mail”在src / authenticate.c中定义。 编译安装。 t相对于用户的主目录。 这样命名为MAILSPOOLHOME 。

[Ekkehard Knopp <knopp@rz-online.de]在qmail-home页面,你可以找到一个procmail-3.11.pre7的补丁,称为procmail-maildir-patch。 当你找不到它,我可以给你一个网络邮箱。 procmail和qmail没有问题。 工作不错

18.13 Qmail:补丁到procmail 3.11pre7与Maildirs一起使用

[Jaye Mathisen mrcpu@cdsnet.net ]在www.qmail.org页面上是一个补丁,可让procmail 3.11pre7与Maildir's(qmail的NFS安全传递格式)配合使用,而Mailbox不可用。

很有用。 真的放缓了交货。 在我的测试箱上,只需将procmail添加到交付中即可发送到默认邮箱,也没有其他规则将我的速度测试从600,000个消息/天增加到大约18万。

杀手。 我怀疑Procmail从星期天锁定Maildir 8路可能是部分怪罪。

18.14 AFS:当HOME在AFS单元格中时如何使用Procmail

...我已经看过关于AFS和procmail的一些存档帖子,但是每个人似乎对这个主题有不同的看法。 除了AFS不是世界上最大的产品之外,大家都同意,当您的$ HOME位于AFS单元格时,是不可能使用procmail吗? 邮件发送本地似乎与procmail一起工作,但邮件从用户w / oa令牌或AFS id只是被传递到/ var / spool / mail /某人。

[Christopher Lindsey lindsey@ncsa.uiuc.edu 1998-03-09 PM-L] AFS真棒! 你只需要很好地对待它。 :)我们可以想到的唯一可行的解​​决方案是修补procmail-3.11pre7源,将用户主目录从另一个目录中删除。

例如,我的主目录在AFS是

      /afs/ncsa.uiuc.edu/.u1/lindsey/

它也保存在/ etc / passwd中的邮件服务器上。 但是,我们通过NFS在/ var / forward中为每个用户设置了一些空间(在我的情况下为/ var / forward / lindsey)。

procmail修补程序拦截用户主目录的请求,并用“假”目录(/ var / forward one)替换它。 所以对于所有实际的目的,procmail的东西,我的主目录是/ var / forward / lindsey,一切都正常。

18.15帮助,一些白痴将我的地址发送到30个邮件列表

您可以制作一个procmailRecipe从列表中垃圾收到的邮件,直到您收到取消订阅的消息,以取消您的参与。 您应该向列表的维护者投诉这样的事情甚至是可能的:邮件列表应该向您发送了一个带有唯一“参与号码”的确认消息,您需要发送回来才能使订阅生效。

      KILL_FILE = $PMSRC/.kill-immediately

:0
*$ ? $IS_READABLE $KILL_FILE
{
KILL = `cat $KILL_FILE`
}

# 1) Make sure KILL has value
# 2) if match is found from header.
# 3) /dev/null does not need lockfile

:0
* KILL ?? [a-z]
*$ $KILL
/dev/null

[sean] ...从长远来看,处理这个问题的最好方法是打破罪犯 - 将这种骚扰引起ISP的关注,并关闭他们的帐户。 必要时重复。 大多数邮件列表应该有一些提交请求的记录。 即使伪造,滥用者也可能在其中的头部有IP地址(如果该人正在积极地将您的朋友订阅到这么多列表,并且实际上在覆盖他们的轨道上工作,显然你已经真正地越过了他们)。 大多数追逐这些不成熟的骚扰策略的人都不够明亮,无法完全掩盖他们的踪迹。

在某些列表上手动处理取消订阅的另一个替代方法是,一旦您确定列表的可过滤特性,即可。 大多数半智能listserv实现将取消您的重复弹跳。 是的,对于listserv维护者来说不错,但是如果也许他们实施订阅验证系统,那么开始就不是一个问题。

      :0
* condition
{
# may expose your .forward - but if you're bouncing lists,
# it probably doesn't matter much.
EXITCODE = 67

# save header for examination.
:0 h:
bounce.log
}

你有一个粘性的情况。 您不能简单地将所有无法识别的邮件淹没 - 您需要先查看潜在的垃圾邮件,并对不属于任何事情采取行动(因为您当然不希望继续获取不需要的列表,直到最后)永远 - 你应该取消订阅他们来简化你的邮件)。

18.16帮助,Procmail发出蜂鸣声并打印到我的控制台

...当消息通过procmail过滤时,我发出哔声,然后前10行也被发送到控制台。 我收到很多信息,所以发出哔哔声,屏幕上的东西变得非常烦人。

[sean]一个或另一个应该做的伎俩(或两者甚至):去你的登录文件(命名取决于你使用的shell),并添加:

      biff -n

或者也可以在.procmailrc中添加:

      COMSAT = "no"

[手动]有关于COMSAT变量的信息。 它还声明(与上面给出的推理相反),如果在命令行中指定rc文件,则COMSAT默认为“否”(否则默认情况下处于打开状态)。

做这个后者应该保持procmail不产生COMSAT / BIFF通知,但仍然会让你的shell能够接收它们,比如说,如果你只是在procmail中手动处理某些邮件或者其他的一些邮件。 就个人而言,我关闭了Biff并关闭了COMSAT。 当我阅读我的邮件时,我读了我的邮件,我经常检查(有一个POP客户端)。

18.17帮助,procmail将邮件转储到控制台

...我已经在我的linux机器上安装了sendmail和procmail(最新版​​本的slackware),它的工作正常,但是procmail如果运行-d $ u转储所有的邮件,立即在控制台上收到----更多--- - 我不喜欢它,哔声是确定,但我不想要我的屏幕上的垃圾。 有没有办法告诉procmail我只想要邮箱在我的邮箱(/ var / spool / mail / $ u)? 谢谢您的帮助!

[Xavier Beaudouin kiwi@oav.net ]检查您的/etc/inetd.conf中的一个in.comstat,在行的开头添加一个'#',保存文件并killall -HUP inetd。 这应该停止这个;-)

18.18帮助,损坏邮箱中的From_行

[Jeffrey S. Gilton jeffg@castlec.com 1998-02-11在procmail邮件列表“解决了FFrom问题”]

感谢所有回答我的问题的人,他们发现From行被破坏的问题。 在这里我告诉什么是真正的问题。

要概述,当我们的Caldera OpenLinux 1.1系统很快收到多个邮件消息时,一些消息会从行上获得多个F,然后后续的消息将丢失F。

大多数答复说,它听起来像一个文件锁定问题。 建议的解决方案是获取最新版本的procmail或重新编译我们的版本,以便查看文件锁定机制。

有趣的是,具有新安装的三个系统没有出现问题。

文件锁定建议最终导致了真正的问题。 在一个好的系统上,我会运行我们的垃圾邮件脚本(我们垃圾邮件自己来触发问题),一切都会奏效。 使用top我会看到procmail的多个实例运行。 看看假脱机文件的目录,我会看到一个spool_file.lock文件被创建,然后离开。

最后,我在系统上做了同样的事情,不行。 在那里我会看到procmail的多个实例运行,但没有创建锁文件。 我对自己说:“现在我知道发生了什么,问题是为什么。”

原来是在spool目录下的权限问题。 在有效的系统上,权限为rwxrwxr-x,所有者为root,组为邮件。 在不起作用的系统上,权限是rwxr-xr-x,所有者和组是root。 这意味着作为邮件运行的procmail无法写入目录文件。 我们将破坏的系统更改为rwxrwxr-x,具有所有者root和组邮件。 问题消失了。

正如我所说,关于锁文件的建议是关键。 它指导我们的调查,直到我们发现真正的问题。 我感谢所有回复的人。

我已经看过关于From行的腐败的其他帖子。 也许你有同样的问题。

[Christopher B. Smith cbsmith@envise.com ]我与升级的OpenLinux系统有完全相同的问题。 为了记录,如果你正在运行它附带的imapd,你应该真正设置你的目录的权限如下:

      chmod 1777 /var/mail/spool

我得到了那个写入imapd的人的反馈,它的效果很好。

18.19将用户的邮件指向HOME而不是/ var / spool /

...我需要将所有单个用户的邮件指向其主目录中的邮箱,以$ HOME / mailbox,

      # One possible solution, not perfect

UHOME = /tmp_mnt/users
UHOME_LIST = "(login1|login2|login3)"

*$ ^TO\/$UHOME_LIST@
* MATCH ?? ()\/[^@]+
$UHOME/$MATCH

[era]如果您有Procmail 3.11pre7或更新版本,可能最好使用^ TO_。 这是使用Procmail的典型案例,您真正需要信封收件人信息。 标题不足以确定消息是谁。 如果Procmail是您的MDA,您可以这样做,但我仍然认为涉及Sendmail的内容将更为合适。 一方面,如果这个用户突然想要使用Procmail怎么办? 您可以在/ etc / procmailrc中为该用户设置DEFAULT和ORGMAIL来解决这个问题,但是像以前那样很多次的底线是Procmail可能不是正确的工具。

18.20 NFS挂载/ var / mail是获得不良性能的好方法

<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/procmail/ 1998-06 / msg00199.html>

      > /var/mail stays at a Solaris 2.5 machine. Cucipop is working
> at the same machine. It's fine there. But, I want to have
> more than one machine with cucipop and when I put cucipop at
> another machines, NFS clients, it is delaying more 30 or 40
> seconds to close the session.

[1998-06-23 PM-L Brad Knowles brad@colltech.com ] NFS挂载/ var / mail是获取不良性能的好方法,特别是在进行任何NFS写操作时。 即使您没有进行任何NFS写操作,只需要处理本地文件锁定并尝试将其转换为NFS文件锁定就是一场噩梦(通常,文件锁定是NFS遗留下来的最大问题之一)。

      > Procmail is working good on NFS, it finishes quickly. But when
> cucipop is put on a NFS client, procmails starts to delay too.

Procmail可能不会写入NFS,或者如果是,它可能不使用与cucipop相同的锁定机制。 不幸的是,每个供应商和每个程序都有自己的想法,如何最好地做到这一点。

[philip] cucipop是由procmail的作者写的。 理想情况下,当您编译cucipop时,您可以编辑其config.h来使用procmail的autoconf进程为您的系统确定的锁定技术。 然而,即使你没有这样做,cucipop也使用与procmail相同的点阵算法。

另外,请注意,任何POP3服务器都必须复制邮箱才能正常工作,并且其中许多服务器将邮箱复制到/var/mail/.username(您获得了“创建大量NFS写入”) 。 完成后,他们将邮箱复制到/ var / mail / username(在他们复制任何新邮件到/var/mail/.username的末尾,然后锁定,然后截断原来的/ var /邮件/用户名文件)。

[philip] cucipop不使用临时文件:它保存在内存中。 在删除时,它会更新mailspool,而不应丢失数据,尽管如果服务器在此中间崩溃,您可能会发现一个或多个虚假消息。

当您开始谈论选择“在服务器上留下邮件”并拥有多兆字节邮箱的用户时,这是一个真正的噩梦。

[philip]假设你有足够的记忆,cucipop应该很快。

我想也许现在你开始明白为什么POP3在多机器环境中真的不能很好地扩展(除非你已经开发了使用真正的数据库后端的自定义邮件存储,比如Oracle Parallel Server)与/ bin / mail(或procmail)作为此消息存储的可写接口,POP3和/或IMAP作为可读(可写)接口连接到同一消息存储区。 那么您可以让数据库供应商处理硬数据复制和分发问题。

否则,这是一个痛苦的屁股。

      > Is there another good pop server?

你是否从高通尝试过QPopper? 这是我曾经遇到的最好的POP3服务器,尽管我甚至不会将它放在NFS写入环境中。

BTW,我曾经是GNR(全球网络导航员)的邮件系统管理员,这是O'Reilly&Assoc的网站/国家ISP合作社。 和美国在线。 在我们的高峰期,我们有成千上万的注册用户,其中多达五到六千人在任何一次登录,他们的MUA设置每分钟检查他们的邮件。

我们有一个主要的邮件/ POP3服务器机器(Dec Alpha 2100 w /四个250Mhz处理器,4GB RAM,28GB硬件镜像/条带邮件假脱机)和一个热备份(相同的CPU / RAM配置,物理挂接到相同的磁盘,但是通过DECsafe ASE不会挂载它们,除非主死亡)。

18.21在LOGFILE中看不到sendmail的响应

...正如手册页所示,这应该写给我的LOGFILE。 没有 但是DID激活配方中的管道。 那么这里有什么?

      :0 hc
*$ ? $IS_EXIST $HOME/.vacation
| LOG=| ($FORMAIL -r; echo $IM_NOT_HERE) | $SENDMAIL -t

[david]手册页面说,变量捕获配方将命令的标准输出分配给变量。 由于您正在修复formail的输出并发回sendmail,所以sendmail吸收了formail和sendmail的标准输出。 Sendmail本身不写入标准输出,所以stdout($ FORMAIL -r; echo $ IM_NOT_HERE)| $ SENDMAIL -t什么也没有。

因此,您将一个空字符串分配给$ LOG,当procmail将$ LOG写入日志文件时,您看不到区别。

18.22编译procmail并选择锁定方案

一般建议:除点锁外的一切通常都是坏的。

[stephen,<199607292139.XAA12433@hera.cuci.nl>] 。 删除fcntl()和lockf(),只允许flock()(或完全省略)内核锁不工作。 但这是所有一些程序使用。 在网络文件系统中,lockf()不起作用,fcntl()和flock()应该是,但是它们不是因为lockd是错误的。 Mailtool使用fcntl()但是错误,这是另一个问题。 在所有平台上,所有网络中唯一可以使用的是.lock文件。

Makefile是指:

      # Uncomment (and change) if you think you know
#LOCKINGTEST=100
# it better than the autoconf lockingtests.
# This will cause the lockingtests to be hotwired.
# 100 to enable fcntl()
# 010 to enable lockf()
# 001 to enable flock()
# Or them together to get the desired combination.

config.h是指:

      /*#define NO_fcntl_LOCK uncomment any of these three if you */
/*#define NO_lockf_LOCK definitely do not want procmail to make */
/*#define NO_flock_LOCK use of those kernel-locking methods */

18.23邮寄大量邮件造成重载

...有几个前进(例如!walter @ localhost)Recipe对于每个转发的邮件,都会创建一个不同的sendmail进程。 这导致系统负载沉重(IMHO难以忍受)。 每个转发的邮件如何阻止procmail运行sendmail进程?

总结:看看qmail,比sendmail好。

[时代1998-08-15 PM-L] (吹灭旧的未充分利用的蝙蝠簿/ ORA sendmail书)是的,将QueueFactor(q)和QueueLA(x)设置为合适的值应该做你想要的。 虽然需要编译负载平衡支持, 根据蝙蝠书,sendmail -d3.1告诉你是否拥有它。 (我只是说getla:0,我想象的意思是我有支持,但负载平均值低于截止水平。

使用负载平均的AFAIK将发送第一个消息,其余的排队。 然而,也不是一个sendmail的大师,我不知道如何清空sendmail队列只用于传入邮件。 此外,即使我知道如何做到这一点,必须在procmail完成后完成。

指导sendmail从procmail调用时排队消息: Liviu Daia daia@stoilow.imar.ro

      SENDMAILFLAGS="-oi -od d"

然后从系统初始化脚本中禁用正常的sendmail守护程序,并以flush队列模式运行,即替换

      /usr/sbin/sendmail -bd -q 15m

在你的init脚本中

      /usr/sbin/sendmail -q 15m

(“15m”是队列运行的频率(15分钟),将其更改为适合您目的的任何内容)。 还要确保在sendmail.cf中禁用分支。

这种方法的缺点是它也会延迟本地邮件的传递。 不同的方法:管道消息sendmail而不是使用'!' 并使用等待标志。 沿着以下方向的东西:

      :0 w
* conditions
| $SENDMAIL $SENDMAILFLAGS <recipients>

嗯,我实际上不确定你可以使用'w'标志没有'f'(手册没有说,我不太熟悉procmail内部),所以如果这不工作,你可能也可以尝试Sendmail将重写From_头(你可以安全地忽略),它会(可选)添加一个From:如果不存在,但它不会触及现有的 From :。 那么实际上它将根据 sendmail.cf中的选项对From中的任何8位字符进行编码或解码,但不会改变“From:”的含义 。 其实这正是procmail在'! Recipe

      :0 fw
* conditions
| $SENDMAIL $SENDMAILFLAGS <recipients>

# dummy recipe to stop procmail from delivering an empty message
:0
a /dev/null

18.24如果MDA Procmail失败,邮件会发生什么

...当procmail是本地邮件代理向用户的$ HOME发送电子邮件,目标机器为“down”时,电子邮件在哪里? 我给人的印象是邮件将在/usr/mail/BOGUS.xxx(Solaris系统)的“mailhub”上收集。 没有发生,我们有丢失邮件的潜力。

[philip]我认为“目标机器”是指给定用户帐户的NFS服务器。 Procmail尝试读取〜/ .procmailrc将超时,然后当它尝试写入$ DEFAULT(你说的是在他们的主目录中)时,它会超时(再次)并将EX_CANTCREAT返回给sendmail。 然后,Sendmail可能会弹出消息。

现在,如果sendmail正在用户主目录中查找.forward文件,那么procmail将永远不会被调用,因为sendmail将尝试打开.forward文件,并在超时时将其视为暂时性错误,导致该消息排队稍后的送货尝试。

(注意:使用-t标志调用procmail会使其返回EX_TEMPFAIL而不是EX_CANTCREAT,这将导致消息被重新排列,但是一般不推荐使用。)

18.25 Procmail将整个90Mb消息读入内存

...上周,当procmail收到一封90Mb的电子邮件(内存不足)时,我的工作站停下来。 关键是,只要系统可以处理,我的邮件大小就可以了。 扫描/ etc / procmailrc /〜/ .procmailrc并对其执行操作之前,有没有办法让procmail只读取该消息的头文件? 这样就不需要将整个消息读入内存。

...最近,我通过procmail将sendmail.cf文件修改为管道消息,然后再发送给它们,以便我可以使用系统范围的procmail配方进行垃圾邮件过滤。 然而,昨天我们有一个客户端发送了一个22兆字节的电子邮件(目的不在此限),系统刚刚跪下试图将其传递到用户的邮箱。

[philip] Btw,我看到的源的所有版本的/ bin / mail(或mail.local)首先将整个消息读入内存或使用临时文件。 根据temp文件所在的位置,90MB的临时文件可能与将其保存在内存中一样糟糕。

而且,不,没有。 黑客入侵并不是不平凡的,主要是因为当前的代码运行时假设整个消息在那里,并且确定何时实际需要查看整个机构(做需求加载)并不容易。 记住一个关于消息大小的条件,ala

      :0
* > 10000000
/dev/null

将要求身体被阅读...真的只是更好的是让sendmail执行限制。 你应该在那里做,以减少完全琐碎的拒绝服务攻击,因为它更有效率。

...我正在运行procmail ver 3.11pre7,我一直在“内存不足”,因为我试图分配8xxxxxx字节。“ 我有超过100兆可用的交换空间,所以我很难理解这一点。 这是一个已知的错误吗?

对于某些OS / libc组合,Procmail的内存分配技术似乎不是最佳的,即实现libc系统函数realloc()(已经报告了FreeBSD)。 可以想象,可以增强配置过程以检测此系统限制,以便在其上更有效地使用策略。 不要压住你的呼吸

[ed]有一个补丁可以解决你的问题。 请参阅<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/cgi-bin / w3glimpse / procmail?query = Albsmeier&errors = 0&case = on&maxfiles = 100&maxlines = 30>上的消息。

18.26帮助,procmail偶尔使用大量的内存

...我们注意到偶尔,procmail使用了大量的内存。 它总是与顶级命令报告的17MB相同。 任何人都可以启发我为什么有时procmail创建这样一个巨大的足迹,其他时候不会,对于同一个用户没有改变的.procmailrc文件?

您的操作系统是FreeBSD还是OpenBSD等BSD变体? 如果是这样,那么问题是由于这些平台上的标准C库系统函数realloc()的执行不好。 可以使用一个可以解决这个问题的补丁。 看到消息

<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/ cgi-bin / w3glimpse / procmail?query = Albsmeier&errors = 0&case = on&maxfiles = 100&maxlines = 30>

具体来说,补丁位于

<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/ cgi-bin / w3glimpse2HTML / procmail / 1997-10 / msg00330.html?63#mfs>。

这是procmail的内存管理工具。 它在处理之前读取一个完整的消息到内存中。 以procmail作为本地交付代理人,系统将系统中的100M CAD文件排除在外。 :-)

18.27 Procmail在我的详细日志中显示出内存不足

...我注意到我的procmail详细日志下面的“事务”:

      procmail: [10239] Sat Jan  9 08:49:02 1999
procmail: Out of memory
buffer 0: "formail"
buffer 1: " formail -A "X-Check: List""
Folder: **Bounced** 5744
procmail: Notified comsat: "bhoule@:**Bounced**"

如果我发生这种情况,我可以做得足够快,我可以查看spool / mqueue,并在To:line中找到一个包含gazillion地址的消息。 所以看来formform在将X-Check头添加到一个已经很大的头文件中时遇到麻烦。

[philip]不,这是procmail无法分配足够的内存。 缓冲区转储表明,procmail无法在解析操作行和达到下一个配方之间获得足够的内存 - 如果procmail已经获得另一个配方或变量赋值,则缓冲区0不会包含字符串“formail”。 什么奇怪的是,消息是如此之小(根据procmail只有5744字节)。 你只看到这个Recipe上的这个错误,或者你的.procmailrc中的随机的地方? 如果以后,那么我会猜测你的邮件服务器出于某种其他原因而失去记忆,procmail恰好是一个无辜的旁观者。 如果是前者,那么,我不太清楚。

信息永远不会传递给我。 有没有什么可以做的,以便procmail / formail将会像以前一样从来没有,所以传入转储到我的收件箱,而不是向邮件程序返回一个错误? 这个“* 反弹 *”业务不是一个非常有用的行动。

给予procmail -t标志将导致致命的内部错误,通常作为永久性错误返回,作为临时故障返回。 否则没有办法控制。 (设置EXITCODE将不起作用,因为procmail需要malloc内存来处理TRAP和EXITCODE,并且它将拒绝尝试导致退出的malloc。)

18.28变量DEFAULT和ORGMAIL

...根据手册页, DEFAULT被定义为ORGMAIL ...所以如果我重新定义ORGMAIL,那么DEFAULT也应该改变,这不利于我。 任何帮助,将不胜感激

[david] DEFAULT最初定义为等于ORGMAIL 。 一旦procmail开始读取/ etc / procmailrc(如果是MDA)或.procmailrc,您可以更改其中的值而不影响另一个。

实际上,您甚至可以在调用procmail时在命令行中设置DEFAULT(但是,我不确定与ORGMAIL一起使用),并且该值将覆盖其正常初始值等于ORGMAIL 。

如果由于磁盘已满,丢失到DEFAULT可能会失败? 那么你最好在另一个文件系统中再放一个地方。 在bdf(1)或df(1)上查看不同的安装文件系统。

      # Place this to the end of your .procmailrc and define
# DEFAULT_SECONDARY

:0 :
$DEFAULT

:0 E
$DEFAULT_SECONDARY

如果您明确地传递给$ DEFAULT,则procmail会将其视为其他保存到文件夹的配方,如果写入失败,则继续阅读配方。

...如果我将“送达”目的地设置为ORGMAIL而不是DEFAULT,会有什么区别吗?

不。 如果你为它编写一个Recipe,procmail只是扩展变量,如果它恰好是与DEFAULT或ORGMAIL相同的目的地,则不会发生变化。 默认是专用于procmail,只有当它脱离rcfile结束后自己使用它; ORGMAIL在启动时是特殊的(不带-m),当procmail脱离rcfile结尾,发现无法将消息保存到DEFAULT 。

一般来说,如果procmail脱离rcfile的结尾,则无法保存到DEFAULT ,然后无法保存到ORGMAIL ,是否还原为ORGMAIL的编译值?

[philip] Procmail不会超出ORGMAIL的当前价值。 如果发送到DEFAULT和ORGMAIL都失败,那么procmail会根据是否给出-t标志放弃并出现错误代码73(EX_CANTCREAT)或75(EX_TEMPFAIL)。 设置EXITCODE可能会覆盖那些。 消息被记录为“*反弹*”。

18.29当DEFAULT不能邮寄到

如果procmail没有传递到rcfile的结尾(或者没有通过INCLUDERC或HOST分配指向另一个rcfile),那么它假定这些:

      :0:
$DEFAULT

:0 e:
$ORGMAIL

也就是说,它尝试传递到$ DEFAULT,如果不能,它尝试$ ORGMAIL。 如果失败了(史蒂芬在“手册页”中说的那么深刻,深刻的麻烦“),它没有交付而退出,并且向MTA报告失败,MTA根据其他因素将会重新提交信件,并尝试稍后提交或将弹出它给发件人

18.30变量DROPPRIVS

...我从一个虚拟域的mailtable调用procmail。 目前以root身份运行,继承自sendmail。 我希望它的运作不那么有特权。 我尝试将rc文件复制到要使用的用户,并设置“DROPPRIVS = yes”。 那没有这样做。 所以我在DROPPRIVS分配之前添加了“LOGNAME = user”和“USER = $ LOGNAME”,并且不起作用。

[philip] DROPPRIVS只有在procmail在传送模式(-d)中运行时使用的/ etc / procmailrc中才有效果,而不是在邮件过滤器模式(-m)中运行时。 USER和LOGNAME对DROPPRIVS的工作没有影响,因为procmail将更改为-d之后在命令行上指定的用户的uid / gid。 您的mailtable条目应该指定procmail邮件程序,它以邮件过滤器模式运行procmail。

如果满足以下条件:

  • procmail以邮件过滤器模式运行
  • 在命令行中没有给出任务
  • 没有指定-p标志
  • 指定的rcfile位于/ etc / procmailrcs /下,无需向后引用(“/../”)
  • rcfile不是一个目录(呃!)

那么procmail将承担rcfile所有者的uid和gid。 如果rcfile实际上是一个符号链接,procmail将假定链接本身的uid和gid,而不是底层文件。 如果您的操作系统允许任何人通过chown放弃文件的所有权,则procmail会对以上内容添加以下限制:

      /etc/procmailrcs must be owned by root and mode 700.

18.31变量HOME

[david]由于procmail不明白波浪号,您必须使用变量HOME。

      CONTENT   = `cat ~/file.txt`        # Won't work
CONTENT = `cat $HOME/file.txt` # ok

但访问其他用户的家是另一个故事。 您可以暂时更改SHELL以获得procmail了解参考,如下所示:

      SHELL   = /bin/csh
CONTENT = `cat ~user/file.txt`
SHELL = /bin/sh # restore original setting

因为波浪号在$ SHELLMETAS中,当procmail看到一个波浪号时,它将调用一个shell。 最好跳过shell的额外进程并使用$ HOME变量:将符号链接放在您自己的主目录下的某个位置,指向其他用户的文件,以便您可以使用.procmailrc中的$ HOME变量并避免shell调用

然而,这也有危险,因为系统管理员可能会移动主目录,并且您的符号链接可能已过期。 如果您期望此类更改和链接断开,那么您可以在需要的时候缓存所需的主目录:

      HOME_PHIL   = `ksh -c "echo ~phil"`
HOME_ED = `ksh -c "echo ~ed"`

18.32变动HOST

[philip]如果分配给“HOST”变量的分配值不在运行procmail的机器的主机名上,则procmail将停止读取procmailrc,如果在命令行中指定了其他procmailrcs ,它将开始阅读它们。

[david]它可以追溯到procmail的早期阶段,在Stephen想到INCLUDERC或“var ?? condition”语法之前。 当人们不得不使用基于本地主机正在处理特定消息的不同代码时,该方法是在procmail的命令行上列出一些rcfiles。 第一个将从所有消息和所有主机的一般代码开始,然后具有

      HOST = some.specific.machine

分配,其次是在该机器上传送的邮件代码。 如果“some.specific.machine”的前九个字符匹配$ HOST的实际值,则procmail将保留在该rcfile中; 在不匹配的情况下,它将跳转到命令行上命名的第二个rcfile。

第二个rcfile可能是另一个特定的机器,所以(除非它首先为除第一个机器之外的所有机器提供了一些通用代码,或者除非只有两台Procmail可能运行的机器)

      HOST = this.specific.machine

再次,前九个字符的匹配将保持procmail读取此rcfile,但不匹配将使其跳转到下一个rcfile。

所以它去了。 一个不正确的HOST分配(注意,“HOST”单独尝试取消设置变量,所以它总是一个不正确的分配)在命令行的最后一个rcfile中,procmail删除消息并退出。 由于我们现在几乎不会在命令行上命名多个rcfile,所以尝试在.procmailrc中取消设置HOST将会产生这种效果。

我猜测,这个原始设置的唯一使用方法是在SmartList中,其中flist在命令行中调用了多个rcfiles的procmail,并使用像HOST = go.to.the.next.rcfile.now这样的东西从一个到下一个 此外,procmail的-m工具(当时不存在)与使用HOST在rcfiles之间跳转不兼容,因为它需要在命令行上命名一个rcfile。

现在我们可以这样做,以便在不同的主机上使用不同的rcfiles:

      :0
* HOST ?? ^^\/[^.]+
{
INCLUDERC = $HOME/.$MATCH.rc
}

18.33变量LINEBUF

... [manual]内部行缓冲区的长度不能设置为小于128.从rcfile读取的所有行不应超过扩展前后的$ LINEBUF字符。 如果没有指定,它默认为2048.这个限制当然不适用于邮件本身...

注意:小心简单地将LINEBUF设置为一个巨大的值:这样一个赋值可以使procmail立即分配两倍这么多内存(procmail内部有两个缓冲区大小为$ LINEBUF)。

[philip]这160条条件几乎肯定溢出了LINEBUF。 您应该a)使用发送到列表的无数Recipe之一,显示使用fgrep; b)将其分解成多种Recipe; 或c)增加LINEBUF。 如果您定期修改这个域名列表,那么您应该强烈地考虑(a),(b)和(c)只是重新发布。

LINEBUF仅适用于procmailrcs的行。 您通常只需要对扩展名或扩展名(back quote)进行扩展或扩展,而对其大小没有明显合理的限制,就需要担心LINEBUF。 procmail将通过忽略额外的输出来执行命令扩展来避免运行其LINEBUF长度缓冲区,因此只要数据截断正常就可以安全执行。 不会像这样检查变量扩展,因此可以通过执行以下操作来导致procmail到core dump:

      :0
* ^Subject: \/.*
|some-program $MATCH

然后向procmail提供一个包含大量主题:标题字段的消息:由于操作中没有出现shell元字符,所以动作行将被procmail直接而不是由shell进行扩展和exec()。 另一方面,以下是好的:

      :0
* ^Subject: \/.*
|some-program $MATCH ; ;

分号强制执行shell调用,shell应该是安全的。 如果你的/ bin / sh可以缓存溢出变量扩展,那么你比你知道的更麻烦。

动作线不是唯一可以观察您的变量展开的地方。 具有领先美元标志的可变分配和条件线也经历了扩张。 例如,这是不安全的:

      SUBJECT = `$FORMAIL -x Subject:`
NEWSUBJ = "Subject: $SUBJECT"

procmail不会在第一行缓冲超载,但是一个很长的主题可能会导致第二行。 以下应该是安全的:

      NEWSUBJ = "Subject: `$FORMAIL -x Subject:`"

但即使如此,只要你确定shell正在扩展NEWSUBJ。

注意,与变量的值匹配(使用“var ??”条件特殊)是安全的,无论变量的内容大小。 问题是当您将变量插入其他内容时。

有没有什么简单的方法来知道特定procmail的默认的LINEBUF值? 我相信有一个更容易的方法,但这将工作:

      #   Mitsuru Furukawa
#
$OUT = $HOME/tmp/linebuf.lst

:0 wc: $OUT$LOCKEXT
*$ ! ? $IS_EXIST $OUT
| echo "$LINEBUF" > $OUT

[philip]如果您检查procmailrc手册页,您将注意到,它列出了14个变量(其中DEFAULT,但不是LINEBUF),其值由procmail在环境中重置,加上一些附加的变量,如IFS,ENV,PWD和PATH这是从config.h的顶部出来的。 以下是所有procmail的魔法变量的列表,其中包括十四个。 这个想法是,虽然procmail有三十个魔法变量,但只有十四个被procmail放入环境中。

其他人可能有默认值,但它们只是“仅输入”:如果您正在做的事情取决于其他具有某个值的其他值,则应该将其设置为该值。 我知道只有两种方法来找出默认情况下procmail正在使用的值:a)检查联机帮助页(手册页面应该显示机器的正确默认值),或者b)启动你最喜欢的调试器,并希望没有人剥离procmail二进制。

Procmail转储核心时不会出现错误信息,尽管原因显然是LINEBUF被超过了太多。

单线长度有限制吗?

[david]是的,在变量扩展和命令替换之前和之后,它必须比LINEBUF字符短。 例外情况是(1)注释和(2)由shell而不是由procmail直接运行的命令。 整个条件必须在LINEBUF字符下

不幸的是,LINEBUF似乎是一个只写变量; 您可以更改其值,但无法找到其当前设置。

18.34变量LOG和LOGFILE

如果你想打印一些东西到 LOGFILE ,你可以这样做

      LOG = "  This message goes to LOGFILE"
LOG = " $NL$NL And this has linefeeds around $NL$NL"

或者像这样,这证明在VERBOSE设置方面有一些不错的功能:

      dummy = "  This message goes to LOGFILE"
dummy = " $NL$NL And this has linefeeds around $NL$NL"

你会看到,如果你设置VERBOSE =“关闭”,那么虚拟行不会被打印并记录到LOGFILE中 。 LOG消息被打印出来,如果您在调用某些子程序时尝试抑制消息,那不是很好:

      saved   = $VERBOSE
VERBOSE = "off"

# Hope this subroutine does not use LOG
# Eg. $PMSRC/pm-jaaddr.rc

INCLUDERC = $RC_ADDR

VERBOSE = $saved # restore original value

18.35可变TRAP

下面是一个如何写入日志文件的例子,请确保已经预设了所有的变量,这只是演示了 TRAP的用法。 如果将值传递给shell,请注意正确使用单引号和双引号。 就像在这个例子中, / dev /从 FOLDER变量的值中删除。

      TRAP = 'echo "
FROM $FROM
TO/CC $TO / $CC
SUBJECT $SUBJECT
FOLDER $LASTFOLDER
" | sed -e "s#FOLDER /dev/#FOLDER #g"'

如果您的MUA希望文件在看到新的邮件之前被Touch,这里是[david]的配方:

      TRAP = 'touch -m $HOME/Mail/$LASTFOLDER' # with strong quotes

把它放在你的rcfile中; 那么保存到目录的每个Recipe可以看起来就像这样,陷阱会照顾到Touch:

      :0 flags # no local lockfile needed for save to directory
* conditions
directoryname/.

[david] Procmail在最终传递邮件后退出...时终止。 在将副本传递到c配方后,它不会终止(也不执行TRAP)[但是,当克隆终止时,克隆确实执行TRAP,除非您为其取消设置TRAP)。 在变量分配,变量捕获配方,过滤配方,以及任何其他非交付操作之后,它不执行陷阱。

另一方面,如果您通过取消设置或遗漏$ HOST来快速纾困,那么它执行陷阱。

[退出时记录主题行的配方]

[david] ...如果有两个或更多,这将在退出时列出日志文件中的所有主题行。 最早会出现两次:一次在陷阱输出中,一次在logabstract中。

      :0
* ^Subject:.*$(.+$)*Subject:
{
# If there is already `TRAP' set, combine the
# old trap recipe with this

TRAP = "${TRAP:+$TRAP ; }$FORMAIL -XSubject:"
}

18.36变量UMASK

如果您使用procmail过滤邮件,则可以找到哪些文件夹包含新邮件的更好方法。 (这是我的一个朋友的骇客)procmail允许你在文件夹上设置UMASK。 所以在做任何事情之前,将UMASK设置为076,这意味着perms将是-rwx ----- x到任何收到邮件的文件夹。 现在使用find -perm -001,您可以打印具有新邮件的文件夹。 这样做的shell脚本也将在所有这些文件夹上都chmod ox。

...这个怎么用? AFAIK umask仅适用于创建的新文件,而不适用于现有文件,这是procmail本质上所做的,对吗?

[时代] Procmail以这种方式解释了UMASK,所以这有效,但我不认为这是一个特别好的解决方案。 在procmailrc(5)中的UMASK的文档中实际上暗示了这一点。 找到一个相当沉重的程序,每次要查找邮件时启动。 (没有做任何时间,但是。)

  • 我只是grep -c'^从'在我的邮件文件夹,看看他们有多少个消息。 (这只是一个近似值,在一个或多个消息包含未转义的From_行的情况下)。
  • 对于一个真正的行人解决方案,将所有的spool文件保存在自己的目录中(我认为这是其他原因的好主意),并在该目录上执行一个ls -lrt,可能用管脚传递到一个sed脚本中,时间戳大于,比如24小时。
  • 如果您的邮件阅读器将在从其中获取邮件时重置假脱机文件的权限,则UMASK技巧是邮件检查脚本的一个很好的基础,但我只需要ls -l的假脱机文件并查找具有x01权限的文件。

18.37 UMASK和权限

我的邮件文件夹-rw-r-rx,Procmail的umask处理是否有错误? (见最后一位x位)

[philip]这是一个功能,而不是一个bug! 引用procmailrc(5)手册页:

UMASK :这个名字说出来(如果没有,那么忘记这个:-)。 分配给UMASK的任何内容都被视为八进制数。 如果未指定,则umask默认为077.如果umask允许o + x,则所有procmail邮箱直接传递将接收到o + x模式更改。 这可以用来检查新邮件是否到达。

无论如何,通常情况下,在Unix下,创建系统调用将设置666的默认权限,umask只能用于屏蔽不需要的位(而不是例如添加x位)。 Procmail不应该这样工作,只是为了与系统的其余部分保持一致?

creat()会将权限设置为任何您想要的权限,模数为umask。 如果umask为零,那么您可以将权限设置为7777,尽管这将是一种愚蠢的事实(实际上,大多数UNIX版本不会让您设置粘滞位和可执行位,除非您是root用户历史原因)。 大多数调用creat()或open(..,O_CREAT,...)的程序给出一个0666的模式参数,因为它们通常不会写出可执行文件。 Procmail刚刚调用open(),模式参数为0667,由你的umask修改。

18.38后退与“|”之间的性能差异 Recipe

Procmail只要看到所有使用的ticks,就会将整个消息发送到stdin。 而如果您使用Recipe,您可以添加 h标志,只将标题只提供给程序,而不是整个消息。 让我们问一下学术问题:下面哪一个选择是有效的?

      # Side effect: Do something with shell
dummy = `echo hi there > some-file.txt`

:0 hwic
| echo "hi there" > some-file.txt

Procmail将整条消息发送到第一行,只发送头到第二个配方。 答:没关系。 无论哪种方式,procmail都会进行一个写入系统调用,它将返回0 [字节写入] ,并关闭它。 你应该使用第一个,因为后者会影响A和E标志,首先是整体上更清晰。

虽然有人建议跟随,但是被拒绝,因为它更多的伤害了表演[stephen] 。 猫的过程是无用的,并指导dev dev不买任何东西。

      :0 hwic
| cat - /dev/null; echo "hi there" > some-file.txt

18.39 Procmail在写入文件时的临时文件名

...任何想法可能会使那些.nfs *文件? 它们包含在.procmailrc的后面部分似乎已由procmail成功处理的消息。 但是,如果我没有发现他们,我怀疑他们会被清理干净。

      /disk3/home/foobar/Mail 119) ls -la backup
total 22
drwx------ 2 stanr 512 Nov 11 21:00 .
drwx------ 3 stanr 2560 Nov 11 21:11 ..
-rw------- 1 stanr 3063 Nov 4 03:31 .nfsA0c724.4
-rw------- 1 stanr 1780 Nov 3 23:00 .nfsA47da4.4
-rw------- 1 stanr 849 Nov 3 23:22 .nfsA481f4.4
-rw------- 1 stanr 2293 Nov 11 11:28 .nfsA737d4.4
-rw------- 1 stanr 2598 Nov 11 20:39 msg.HCJB
-rw------- 1 stanr 3127 Nov 11 21:00 msg.ICJB
-rw------- 1 stanr 1884 Nov 11 20:45 msg.KCJB
/disk3/home/stanr/Mail 120)

[david] procmail在尝试写出一个文件时使用临时名称,如果事情顺利,它将重命名。 我注意到他们都是过夜的4小时31分钟。 也许在你的机器上有一些系统工作正在搞砸了吗?

      :0 ic
| cd backup && rm -f dummy `ls -t msg.* .nfs* | sed -e 1,3d`

[aaron]当NFS客户端上的程序使用的文件被取消链接时,NFS服务器将其重命名为类似的东西。 当文件关闭时,应该实际上取消链接,但是看起来NFS服务器从来没有收到关闭的消息。

[Keith Pyle keith@ibmoto.com ]这是使用NFS的结果,但是NFS客户端上的操作系统的错误。 请记住,从NFS服务器的角度看,NFS是无状态的。 它不保留任何文件被使用的信息。 因此,如果客户端告诉服务器删除该文件,则服务器会删除该文件。 这通常不是问题,但是许多程序使用Unix的“技巧”,程序打开文件,取消链接(删除),然后继续使用该文件。 对于所有本地文件,Unix内核将不会实际删除文件,直到所有打开文件的进程退出。 这对临时文件非常有用。

如果一个客户端告诉NFS服务器删除一个文件,它会立即删除文件,因为NFS的无状态。 服务器无法知道任何客户端是否仍然有文件打开。 为避免此问题,如果客户端取消链接NFS文件系统上的打开文件,则该文件将重命名为.nfs *,其中*是唯一值。 NFS客户端系统应该在进程退出时删除.nfs *文件。 但是,有些版本的Unix不能很好地执行(例如AIX)。 如果使用这些操作系统之一,通常在各个地方找到.nfs *文件。 因此,系统管理员在一定年龄内定期清除任何.nfs *文件是一个好主意,以消除文件系统中的难看的构建。

18.40参数$ @

[david] 3.11pre7 procmail版本没有格式化“$ *”,也不会在管道或转发操作之外的“$ @”。 将位置参数全部引用为“$ *”的唯一方法就是这样:

这毕竟不行

      ARGS = `echo "$@"`

Procmail将“$ @”替换为null。 尽管如此,

      :0 ir
ARGS=|echo "$@"

之后,您使用“$ ARGS”而不是“$ *”。

如果您尝试使用ARGS =“$ @”设置ARGS,则procmail不会替代“$ @”并使$ ARGS为空。 如果您尝试ARGS =“$ *”,您将获得文字“$ *”。

[philip]当然,$ ARGS与$ @有很大的不同之处在于,ARGS将被分割为空格(如果未引用)或一个参数(如果是双引号)。 $ @有酷的属性,如果双引号,它仍然会被分割成原始参数边界上的多个参数。 由于邮箱地址通常都有空格,所以这个区别不应该随便被驳回。 请注意,虽然您可能不会键入这样的地址,但您的MUA的回复构建者可能会。

18.41 Procmail变量为空终止(检测空字符串)

您不能在消息中捕获null。 如果你尝试这样的话

      NUL=`/usr/bin/echo "\000"`

:0
*$ HB ?? $\NUL
{
LOG = "Caught NUL"
}

[philip]它不会按预期工作。 问题是环境变量(因此procmail变量)是空终止的,因此不能包含一个null。 上述行创建一个空变量。 解决方案是使用反转字符类:

      NUL = `/usr/5bin/echo '[^\001-\377]'`

请注意,procmail处理procmailrcs中除了null之外的8位字符,因此您可以在.procmailrc中使用文字控件-A和octal-377,并在其中保存echo和shell调用。

18.42 FROM_DAEMON TO和TO_以及案件敏感性

[david] ^ TO默认情况下不区分大小写。 斯蒂芬曾经告诉我一些令牌,比如^ TO,^ TO_,^ FROM_DAEMON和^ FROM_MAILER的标记 总是不区分大小写的,即使Recipe有 D标志,但我不是那么肯定,那就是他是说,我们从来没有追求过。 当然,如果没有 D,他们对案件不敏感。

[philip]如果正则表达式包含^ FROM_DAEMON令牌,那么整个正则表达式将被视为不区分大小写。 Recipe中的其他条件不受此影响。 其他令牌对案件敏感度没有影响。 (这是与procmail 3.11pre4)

18.43 TO_宏解密

... TO和TO_之间的本质区别是什么?

[phil 1996-03-21]区别在于^ TOalias1 @ site可能匹配像bobs-alias1 @ site,而^ TO_不会。

[elijah 1997-09-16]我们用perl / x格式重写。 见下文。 方框(E)中字边界的定义。 见下文。 ^ TO_扩展已添加到v3.11pre4中。 你可能只需要^ TO(不是'_'),这应该是几乎一样的工作。

      /                       # [begin regexp]
( # [Block (A)]
^ # Anchor to start of line
( # [Block (B)]
(Original-)? # Optionally proceed (C) with "Original-"
(Resent-)? # Optionally proceed (C) with "Resent-"
( # [Block (C)]
To # "To"
|Cc # or "Cc"
|Bcc # or "Bcc" {very rare in practice}
) # [end (C)]
| ( # [Block (D)]
X-Envelope # Proceed line 17 with "X-Envelope"
|Apparently # or "Apparently"
(-Resent)? # with optional "-Resent" appended
) # [end (D)]
-To # "-To" [line 14]
) # [end (B)]
: # ":"
( # [Block (E)]
.* # any text
# any single char other than letters, numbers,
[^-a-zA-Z0-9_.]
# hyphen (-), underscore (_), or period (.)
) # [end (E)]
? # Block (E) is optional
) # [end (A)]
/x # [end regexp]

18.44 TO_宏和RFC 822

...根据RFC822,From地址可以包含几乎任何东西,只要它包含在<...>之间,可以从行中提取有效的邮件地址。 像foo@example.com。

[Vikas Agnihotri vikas@insight.att.com ]块(E){见TO_宏解释}是在那里sl up那部分。 <encapsulation>不需要,例如:

      From: "jester@fun.house" <EM>fool@aol.com</EM>

将混淆“^ TO_jester @”的测试。 是的,我看到人们做这些事情,显然甚至不是恶意的。 虽然有效的以下也是有效的

      From: someone@somewhere.com <EM>another@one.com</EM>

[以利亚继续]也会混淆正则表达式。 我不喜欢大多数东西的^ TO和^ TO_宏,通常使用这样的东西:

      ^(Resent-)?(To|CC):.*[< ]{address}([ >]|$)

它仍然可以混淆,但是在实践中会引起问题的事情相当罕见。 你可能会喜欢这样的:

      ^(Resent-)?(To|CC):([^(]+([(].*[)])?)*[, <]{address}([, >]|$)

哪个可以正确处理

      To: (hatter@tea.party) {address}
To: (fake {address}) bill.the.lizard@the.jury.box
To: Alice <EM>alice@the.croquet.game</EM>, "W. Rabbit (late)"
<EM>hare@small.hole</EM>, Gentle Reader <{address}>
To: jabberwocky@vorpal.swords.r.us, duchess@the.croquet.game,
chesire@no.where, {address}, dinah@meow.org

它仍然会失败

      To: (fake <{address}>) mockturtle@tortoise.edu

如果有人有恶意给你发送这样的邮件。

18.45 FROM_DAEMON解密

这是从3.11pre7开始爆炸的FROM_DAEMON regexp

      (^(Precedence:.*(junk|bulk|list)
|To: Multiple recipients of
|(
((Resent-)?(From|Sender)|X-Envelope-From):|>?From )
([^>]*[^(.%@a-z0-9])?
(
Post(ma?(st(e?r)?|n)|office)
|(send)?Mail(er)?
|daemon
|m(mdf|ajordomo)
|n?uucp
|LIST(SERV|proc)
|NETSERV
|o(wner|ps)
|r(e(quest|sponse)|oot)
|b(ounce|bs\.smtp)
|echo
|mirror
|s(erv(ices?|er)
|mtp(error)?|ystem)
|A(
dmin(istrator)?
|MMGR
|utoanswer
)
)
( ([^).!:a-z0-9][-_a-z0-9]*)?
[%@> ][^<)]*(\(.*\).*)?
)?
$
([^>]|$)
)
)

[时代]解释最后的正则表达式如下:

      (([^).!:a-z0-9]   End of e-mail address token
[-_a-z0-9] Another alpha token
)? ... or maybe not;
[%@>\t ] Address separator -- either <EM>address@...</EM> or
<address> or a bare address with whitespace
around it
[^<)]* Skip as long as we don't run into another
bracketed address or end of comment
(presumably to prevent this from matching
inside parenthesized comments in the first
place)
(\(.*\).*)? Skip optional parenthesized comments and
anything after them if found
)? ... or maybe not; maybe we just see an ...
$ ... end of line instead
([^>]|$) Uh, I should know what this is supposed to do,
but I can't quite remember what it's for. I
think it had something to do with continued
header lines ... Anyone?

返回路径上的^ FROM_MAILER是否匹配?

[david 1998-04-29]显然不是,但它在UNIX From_行匹配,通常它包含与Return-Path:头相同的地址。

有人有一个想法如何使用这个宏,但告诉它忽略标题中的返回路径行?

在procmail中可能还有一些方法,没有额外的formail分支,但这是很容易想到和容易写的:

      :0h
HEAD_WITHOUT_FROM_=| formail -IReturn-Path: -I'From '

:0
* HEAD_WITHOUT_FROM_ ?? ^FROM_MAILER
action

如果您只想考虑From:头,请尝试:

      :0
* ^\/From:.*
* MATCH ?? ^FROM_MAILER
action

19.0技术性事项

19.1退出代码清单

正确的地方是/usr/include/sysexits.h,但代码应该是非常标准的。 这些来自HP-UX 10,主要使用的代码是EX_NOUSER或EX_NOPERM。 它告诉UBE的发件人“从你的名单中删除我并删除我;我不在这里”

      EX_OK          0        successful termination
EX__BASE 64 base value for error messages

EX_USAGE 64 command line usage error
EX_DATAERR 65 data format error
EX_NOINPUT 66 cannot open input
EX_NOUSER 67 addressee unknown
EX_NOHOST 68 host name unknown
EX_UNAVAILABLE 69 service unavailable
EX_SOFTWARE 70 internal software error
EX_OSERR 71 system error (e.g., can't fork)
EX_OSFILE 72 critical OS file missing
EX_CANTCREAT 73 can't create (user) output file
EX_IOERR 74 input/output error
EX_TEMPFAIL 75 temp failure; user is invited to retry
EX_PROTOCOL 76 remote error in protocol
EX_NOPERM 77 permission denied

我以为通过使用EXITCODE,我会放心邮件将被拒绝,但事实上Sendmail 8.8.7试图将“用户未知”提交给netcom.com,这显然是错误的?

[sean] Sendmail接收消息,然后将其传递给Procmail,作为本地传送代理,或通过.forward文件(取决于您的系统配置)。 Procmail说“哎,谎言不在这里”,并且拒绝这个消息,什么时候被送回线轴,并根据谁出现来交付。

如果SENDMAIL确定用户不存在(密码文件/别名/ virtusertable.txt),那么当远程执行SMTP RCPT时,它将拒绝该消息。 但用户WAS有效,所以接受它。

另一种情况是当您有一个邮件辅助,您的主要(用户帐户和procmail的位置)已关闭。 某些系统会向您发送邮件,并解析为您的辅助邮件 - 它只是为您的主要邮件保存邮件 - 它不是一个线索,哪个用户是有效的,哪些不是。 那么(E)HELO(发送你的主要消息的系统)发生在SMTP会话期间,消息来自你的辅助节点,而不是从原始的发送者。 在这一点上,如果用户不存在,我相信sendmail会向次级发送一个未知的用户错误,反过来应该将该消息发送回发送者的身份(我无法查看我的蝙蝠图书从我所在的地方 - 欢迎任何sendmail专业人士详细说明)。

有什么办法来解决这个问题(强制在交货时候拒绝)? 更好的是,有没有一些检查,以确保收到的域合理地匹配From:域?

您需要在SMTP守护程序(通常是Sendmail)中设置一个规则集,以检查域(在许多有效邮件BTW上将失败),并拒绝SMTP传送会话(实际上是协商)正在进行中。 在Procmail有消息的时候,您完全接受了该消息,您可能希望做的任何拒绝都是将邮件反弹到明显的发件人。

这是伪造邮件的问题。

我不会建议这种打击垃圾邮件的策略 - 其中大部分是伪造的,发出的任何反弹只会使用您的机器上的系统资源和被欺骗的系统上的系统资源。 垃圾邮件发送者不会从他们的列表中删除地址(他们希望列表看起来尽可能大,当他们出售给别人时) - 有些甚至采取了在域上生成地址并发送消息给他们的假设有人可能会有这个名字的帐号(“bill @ joe @ dave @ ...”)。

使用procmail来垃圾邮件(或者以其他方式存档)所有的垃圾,然后手动对通过的人采取行动。

19.2优先代码清单

大多数发送邮件识别的优先级是以下。 优先级越低,邮件处理的时间越晚。 智能休假计划将忽略列表,批量或垃圾优先级的任何内容。 - Adam Shostack adam@bwh.harvard.edu

      0   first-class
30 list
60 bulk
100 junk
100 special-delivery

[dan]当您通过文件服务器分发文件时,应该使用批量 。 优先级:标头中的值对消息本身的内容绝对没有任何意义,它只是建议邮件系统的优先级。 从O'Reilly的sendmail书的第668页,批量通常的值为-200,而垃圾 -100; 因此,与垃圾邮件相比,消息将具有比批量 更高的优先级(尽管这可以在sendmail.cf文件中更改)。

除了在重负载的机器上,这个值不会重要,因为所有邮件都将被快速处理。

[Stephen] ...一个人发送的邮件通常被认为比一些守护进程生成的autoreplies更重要。 表示自动复制的较低优先级的一种方法是添加“优先级:垃圾”字段。 这允许邮件传输代理人首先对哪个邮件进行有针对性的决定(如果邮件队列被堵塞)。

另一点是:其他自动回复服务,如度假 。 他们尽量不要意外地回复另一个守护进程(例如你的)产生的消息。 他们检测到的一种方法是通过查看“优先级”字段。 如果它含有垃圾 ,他们知道,这不是我们应该回应的。

19.3 Sendmail和-t

sendmail -t标签读取To,Cc,Bcc等为自动响应的收件人?

      :0h
* condition
* !^X-Loop: foo@site\.com
| ($FORMAIL -rA "X-Loop: foo@example.com" ) | sendmail -oi -t

[david]这不是问题,因为formail -r不会生成任何Cc或Bcc:标头,除非你告诉formail来添加它们。 sendmail -t将寻找收件人的唯一行将是To:行。

19.4 RFC822多个收件人的回复和成功问题

[david] formail -r只提取一个返回地址,即使Resent-Reply-To:或Reply-To:头包含多个(而Stephen也告诉我他打算这样做)。
  • 寻找最好的地址回复是一个完全不同的算法,而不是寻找最好的地址组来回复。 查找一组地址涉及确定您甚至正在搜索一个组,而不仅仅是一个地址。 然后找出每个的最佳地址。 一个地址已经是一个棘手的事情了。
  • 数以千计的自动备份配方容易受到邮件风暴的攻击。 即使由不知道他在做什么的人操作,Formail也尽力控制伤害。 有时,如果要对多个地址进行回复,则这种损害控制被严重破坏。

[dan]我明白这些关切 然而,RFC822特别允许在Reply-To:头中的多个收件人。 鉴于此,似乎应该有一个直接的方式来处理这个问题。 更糟糕的是,“formail”默认忽略多个Reply-To:地址。

对于(a),答复:(或Resent-Reply-To :)标题不会取代所有其他地址,从而大大简化搜索? 对于(b),如果还指定了formail的“-t”选项,那么如何使用多个(Resent-)Reply-To:address呢? 或者如果你真的担心邮件风暴和现有的Recipe,一个新的formail选项。

19.5 Procmail和IMAP服务器

[ed]另见 ftp://ftp.cac.washington.edu/mail/imap.vs.pop ...本文是一篇简要说明,题为“比较远程邮箱访问的两种方法:IMAP与POP “,这是1993年写的,最近更新了。 本文的目的是提供更广泛的消息访问范例和协议背景,然后在“在线”操作的上下文中特别比较互联网的邮局协议(POP)和互联网消息访问协议(IMAP)。

...我登录到一组NFS-ed服务器(或更准确地说是AFS-ed),我的邮件进入运行IMAP的另一个服务器(不是此集合的一部分)。 所以sendmail从来没有在我的登录机上将邮件传递到/ var / mail / $ LOGNAME中,而是传递到IMAP服务器。 由于sendmail从未在主目录中读取我的.forward文件,所以我认为procmail永远不会被调用。

您需要一个程序,该程序将从IMAP服务器获取电子邮件,然后将其提供给procmail。 一个这样的程序可以做到这一点是fetchmail。 查看http://locke.ccil.org/~esr/fetchmail/ 。 坏消息是,一旦您这样做,您可能无法使用IMAP客户端再次阅读您的电子邮件。 但是,如果您更喜欢MUA读取mbox文件但并不影响IMAP,那么这可能是个好消息。

19.6处理邮件的机器

...刚刚安装的procmail不起作用,我假设sendmail试图在另一台机器上运行procmail。 有没有办法我可以找到相应的架构为该机器

[时代]以下内容应该告诉你处理您要询问的机器的邮件的机器的名称。 然后,如果您有shell访问,那么您可以尝试登录到该计算机,这是为了在其上编译Procmail所需要的。

      nslookup -q=mx machine      # alternatively use host(1) command

如果你没有nslookup(doh)或者不明白它是什么,请尝试将它添加到你的.forward中

      "|uname -a >/full/path/to/home/.uname.out"

除了你做什么外,还应该在那里。 否则这将彻底丢失您的邮件,因为它读取邮件,但不保存在任何地方。 您也可以将所有传入邮件的副本保存到安全邮箱中,以防万一。 像这样:

      /full/path/to/home/safetymailbox
|"uname -a >/full/path/to/home/.uname.out"
|"IFS=' '&& exec /usr/local/bin/procmail -Yf- || exit 75"

如果您尝试这样做,这是非常重要的文件安全邮箱存在和可写。 ( 男人 5 前进,如果你有这个 - 我似乎没有这个手册页面的系统与新的版本的sendmail,是正确的?)

尝试uname命令(和/或阅读手册)以查看您应该在文件.uname.out中找到什么

19.7编译procmail和MAILSPOOLHOME

...我在一个新系统上编译了3.11pre7,并有几个问题。 我将makefile编辑为主目录“/ home / a / abc”。 我将MAILSPOOLHOME定义为“/ mail”。 传入邮件实际上存储在“/ usr / mail / abc”中。 当我通过procmail管道测试消息(使用“procmail </ usr / mail / abc”),而不是他们结束在我的收件箱,他们最终在一个名为“msg.gs.KB”的邮箱。 我做了什么? 当我坐在这里考虑一下,MAILSPOOLHASH应该设置为1而不是0?

[philip]如果传入的邮件应该存储在/ usr / mail / loginname,那么你不应该定义MAILSPOOLHOME,而是将MAILSPOOLDIR定义为“/ usr / mail /”,并将MAILSPOOLHASH设置为0.定义MAILSPOOLHOME会导致邮件被传递到内部的每个用户的主目录,这似乎不是你想要的。 MAILSPOOLHASH会导致假脱机目录中的层次结构增加,从而避免“胖慢目录”问题。

20.0 Emacs Procmail软件

20.1什么是Emacs?

...我在Unix机器上学到的第一件事是, vi是一个文本编辑器, Emacs是一种生活方式。 --David W. Tamkin dattier@wwa.com

Emacs是一个编程平台(它不仅是一个文本编辑器,也是一个编程编辑器,但几乎可以在几乎所有Unix平台上都可以找到几乎所有你所要做的一切,除了做你的咖啡)。 现在,Emacs也可用于PC平台。 有两种口味可供选择:由FSF(自由软件基金会)维护的Emacs和有时称为“Emacs下一代”的XEmacs,因为它具有更好的图形用户界面(gui)和内部高级OO设计(它可以突出显示tty,而Emacs不能)。 XEmacs由一组编程向导维护。 Emacs加载项包是lisp,lisp文件扩展名是.el 。 在每个包中,可以找到使用说明,以及如何将包安装到Emacs中。

20.2 Emacs procmail模式和Procmail代码检查(Lint)

可以使用Emacs的Procmail模式(也可以使用lint procmail配方)。 熟悉C编码的人知道lint,这是一个严格的代码语法检查器。 您可以从 http://tiny-tools.sourceforge.net/阅读有关Emacs模式

20.3为什么使用procmail与Gnus

Gnus < http://www.gnus.org >包括非常强大的邮件分割方法,一个反对procmail需求的正常反应是:“嘿,Gnus我的邮件分割,我不需要procmail”。 Gnus和procmail分割之间的区别很容易解释:你希望procmail在gnus看到它之前预处理邮件,然后使用Gnus对邮件进行后处理(读取,将邮件从收件箱移动到另一个)

案例1 :Gnus和常规邮箱,没有procmail。 Gnus直接读取所有传入邮件的一个庞大邮箱。 当用户启动Gnus时,它会在整个邮箱中显示,并根据其拆分规则开始拆分邮件。

      mail -> $MAIL --> fire up Gnus  --> split1.mbx split2.mbx ....

案例2:procmail和Gnus。 邮件总是先交给procmail。 Procmail可以随意将邮件放在任何地方,也可以放在用户的默认收件箱中,通常由环境变量$ MAIL指出。

      mail -> procmail                --> Post processing with Gnus
[the ~/Mail/spool]
--> split1.mbx
--> split2.mbx
[The default procmail rule drops to inbox]
--> $MAIL

您可以让gnus进一步处理消息:就像将消息从一个收件箱移动到另一个收件箱。

概要

  • 如果您使用procmail,则会立即对传入的邮件进行分类。 收到的邮件将放在您选择的文件夹中。 这些邮箱都在等你。 您可以使用较少或更多的方式来匆忙查看。
  • 如果你不使用procmail,让Gnus做所有的分裂,你总会看到一个巨大的收件箱$ MAIL。 在你启动Emacs和Gnus之前,它不会分裂。 如果您匆忙,您可能没有时间在阅读重要信息之前启动Emacs&Gnus。 您唯一的选择是阅读$ MAIL中的所有邮件,并尝试找到像您工作的那些。

所以,让procmail将邮件放到他们的收件箱和Gnus中,以便对这些收件箱进行“精细处理”。

20.4设置Procmail的Gnus - 基础知识

Procmail和Gnus在使用邮件后端如 nnml , nnmh和 nnfolder时,可以 很好的 沟通 。 请参阅Emacs info Gnus :: Node: 选择更多的 方法 。

以下是使用nnml邮件后端阅读邮件的一步一步的说明。 我们假设您的procmailrc中有以下定义,以便将传入的邮件传递到右侧
目录。

这里的重点是gnus nnml组的名称是相同的; proqail写的spool文件除了.spoolPostfix之外。 所以如果你写到list.procmail.spool , gnus中的组名称命名为nnml:list.procmail

      #  .procmailrc excerpt

PMSRC = $HOME/pm
MAILDIR = $HOME/Mail
SPOOL = $MAILDIR/spool
RC_LIST = $PMSRC/pm-jalist.rc

# The file name must be list.xxxxx.spool in order to
# `nnml' to work in Gnus.Define procmail mailing list

PROCMAIL_SPOOL = $SPOOL/list.procmail.spool

# GNUS must have unique message headers, generate one
# if it isn't there. By Joe Hildebrand <EM>hildjj@fuentez.com</EM>

:0 fhw
| $FORMAIL -a Message-Id: -a "Subject: (None)"

# detect mailing lists and store messages to spool directory

INCLUDERC = $RC_LIST

:0 :
* ! LIST ?? ^^^^
$SPOOL/list.$LIST.spool
  • 将下面的Lisp代码复制到你的〜/ .gnus
  • 用Mx gnus-no-server启动Gnus(Mx表示ESC后跟x)。 您将看到缓冲区出现。
  • 使用G m list.procmail RET nnml RET创建新组。 您可以照常阅读该组,并使用g命令查询新邮件。

      (setq
gnus-secondary-select-methods '((nnml ""))
;; See also nnmail-procmail-suffix which is .spool by
;; default
;;
nnmail-use-procmail t
nnmail-spool-file 'procmail
nnmail-procmail-directory "~/Mail/spool/"
nnmail-delete-incoming t)

然后我有procmail总是提供〜/ Mail / spool /。 如果您添加更多收件箱,请在Gm中使用Gmus 缓冲区创建它们。

20.5 Gnus for procmail - 更多关于它

好的,我们继续在Emacs旅程。 你以前读过的是让你的Gnus读取procmail传递文件所需的最小值。 但是,如果你刚刚接触Gnus,这里有一些更多的提示和基本的说明。 我可以给出的最好的建议是你去每个缓冲区:在组中,按 G Ch和Summary Ch m ,并将命令打印到您看到列出的打印机。

在组缓冲区

  • 当您按g获取新邮件到这些组时,如果没有邮件,该组将消失 。 如果您希望该组永久可见,然后设置

      (setq gnus-permanently-visible-groups  "^nnml\\|^nnfolder")

In emergency, press `L' to list all groups.
  • 如果您发生错误,并在组名中偶然添加了list.procmaill,请使用G r重命名组。
  • 使用S l提高或降低您的procmail邮件组的优先级。 值1或2或3是好的。 考虑预留1份您的主要邮件,2份和3份邮寄名单。
  • 当您退出群组并阅读了一些文章时,下次不会出现。 但是通过在使用SPC进入组之前提供前缀参数,Gnus将列出所有阅读的文章。 你给出像Cu SPC这样的命令,其中Cu是前缀参数。

设置

  • 你想要gnus告诉你它做的一切

      (setq gnus-verbose 10)  ;; 0..10
  • 您可以在Summary缓冲区中使用'E'命令来过期文章(永久删除它们)。 默认到期时间为7天。 您可以用天数来定义到期时间

      (setq nnmail-expiry-wait 7)
  • 如果您阅读邮件列表,则在阅读文章时,您希望自动到期。 使用以下方法设置使用此自动过期的组。

      (setq gnus-auto-expirable-newsgroups
(concat
"procmail"
"\\|other-list"
"\\|and-some-other-list"))

  • 汇总缓冲区中的B e将过期当前可接收的文章。
  • 如果你想杀死一篇文章; 永久将其从磁盘中删除 ,使用B 删除 。
  • 如果要将文章标记为持久性 (永不过期),请使用*
  • 您不希望这些邮件组被缓存,因为邮件已经处于“缓存”格式。 只有当您阅读新闻组并希望在本地存储消息时,才需要缓存。

      (setq gnus-uncacheable-groups "^nn\\(virtual\\|m[hlk]\\|db\\)")

20.6 Emacs和Gnus - 使用假脱机文件

那么,告诉你真相,管理Gnus起初是可怕的:你可以在路上犯下很多错误,或者改变你对群组名称等等的想法。 如果您决定重新命名procmail放置过滤后的邮件的假脱机文件名,则将邮件从一个目录移动到另一个目录是一项棘手的任务。

我们来举个例子:假设你决定将spool文件名list.procmail.spool更改为mail.procmail.spool,因为你认为所有的邮件组都应该有相同的前缀“mail”。 在你的Gnus组缓冲区。 您已经将procmail更改为输出到该文件,因此现在您有两个文件位于spool目录中。

      ~/Mail/spool/list.procmail.spool
~/Mail/spool/mail.procmail.spool # make sure this exists
  • 让Gnus照常阅读旧文件。 按g读取新邮件到list.procmail 。 list.procmail.spool现在将为空,并合并到nnml后端文件nnml:list.procmail。
  • 缓冲区中使用G m nnmail mail.procmail创建一个新组。
  • 转到旧的list.procmail组,并选择所有文章与M P a 。 将带有B m的邮件移动到mail.procmail 。 您会看到G标记出现在移动文章的开头。
  • 退出Summary缓冲区,然后点击g ,看到邮件帽被转移到新的mail.procmail
  • 使用G DEL杀死旧组list.procmail
  • 还有一件事,删除那个空的文件。 它不再用于任何东西。

      % rm ~/Mail/spool/list.procmail.spool

20.7 Gnus文章片段

[这些文章是从GNUS超文本存档中收集的]

我也有一些困惑与提出的解决方案procmail过滤接收邮件在nnmail-procmail目录而不是。

您有Procmail的邮件在假脱机文件中,预先排序并过滤。 Gnus然后选择这些并将消息填充到适当的组中。 Gnus使用movemail实际上将邮件从线轴移出,而移动邮件使用Procmail所理解的锁定,所以没有邮件丢失的危险。

为什么nnfolder-directory和nnmail -procmail-directory两个不同的目录,如果nnmail -procmail-directory将包含procmail所附加的邮箱,并且nnfolder-directory应为“所有nnfolder邮箱将存储在此目录下” ?

因为Procmail应该将其邮件放在不同的文件夹中, 而不是在您的普通邮件中存储邮件。

想法是让Gnus使用nnmail -procmail-directory作为从其处理的临时目录,然后在nnfolder目录中存储nnfolder邮箱 ?

是的 - Jason L Tibbitts III(tibbs@hpc.uh.edu)

Procmail设置

      (setq nnmail-use-procmail t)
(setq nnfolder-directory "~/gMail/")
(setq nnmail-spool-file 'procmail)
(setq nnmail-procmail-directory "~/incoming/lists/")
(setq gnus-secondary-select-methods '((nnfolder "")))
(setq nnmail-procmail-suffix "")

Procmail将传入邮件添加到〜/ incoming / lists / listname。 我订阅的nnfolder组命名为“nnfolder:lists.listname”Gnus确实在每个列表的目录中创建一个零长度文件的〜/ gMail / lists目录,但不会移动任何邮件,所以它认为我有“没有更多未读的新闻组”。

      (nnmail-get-spool-files)

经过多次实验,我终于得到了移动邮件的工作。 我将nnfolder目录更改为“〜/ gMail / lists /”,Gnus现在将邮件从“〜/ incoming / lists /”移动到“〜/ gMail /”中的相应组。 我的问题似乎得到解决,但是这些工作似乎对我来说是直觉的。 通过关于nnfolder目录的手册,我会认为Gnus应该在“〜/ gMail / lists /”中构建nnfolder组,而不是给出我的定义。

我认为nnmail希望spool文件被称为“〜/ incoming / lists.whatever”,而不是“〜/ incoming / lists / whatever”。

      (setq nnmail-procmail-directory "~/incoming/lists/")

我以为你说这些团体被称为“lists.whatever”? 所以spool文件叫〜/ incoming / lists / lists.whatever.spool,那么?

21.0 RFC,请求注释

21.1 RFC及其管辖权(绿色地址)

尝试dejanews <power seach>组:gnu.emacs.gnus搜索:RFC

新闻软件的真正实现并不在意,如果来自该领域是不是绿色的

[1998-03-25 gnus.emacs.gnus,Marty Fouts fouts@null.net ]论点是:RFC不要求那些引用他们的人抑制他们所做的声明。 特别地,RFC 1036是一个咨询, 试图描述netnews如何使用NNTP。 在标题显示的情况下,RFC 1036 没有描述软件在现场工作的方式。 没有理由引用一个咨询RFC,在许多方面是不正确的,以支持一个站不住脚的地位。

注意: Marty是IETF USEFOR,对RFC应如何解释有很好的了解。 见gnu.emacs.gnus 1999-02-08和那里/ Re:“发件人”字段/。 <URL: http : //search.dejanews.com/msgid.xp?MID=%3Cy1ud83pre7w.fsf@acuson.com%3E&format=threaded&maxhits=200 >

[1997-11-05 gnus.emacs.gnus,Marty Fouts]没有RFC强制海报的地址是可达到的地址(实际上,发件人:有时是没有域名的用户@主机) - 它只需要这样地址在语法上是正确的。 RFC不需要任何东西。 与Usenet相关的RFC是咨询 。 RFC描述各种事物并定义少量的标准协议,netnews 不是互联网标准协议。)

  • 并非所有的RFC都是标准
  • RFC 1036 明确指出,它不是互联网标准。
  • RFC 1036和822 WRT到RFC 1036标题的措辞是不明确的。 RFC 822 具体描述了邮件的格式。 它不描述电子邮件地址的完整格式。
  • 1036年没有地方有需要地址可以交付的语言。 此外,822提供了允许有效但不可交付的地址是可接受的语言。 [822没有描述地址,它描述邮箱 ,这是类似但不完全相同的。]

信息的底线WRT RFC是当RFC和实现之间存在歧义或差异时,执行(这是RFC首先要描述的)的先例。

就像你想要的那样, netnews (IE INND,NNTP)的实现不关心地址是否可以回复。 据传有些新闻发布软件检查地址的有效性。 这样的软件在一部分。

[counter argument 1998-03-25 gnu.emacs.gnus,Jan Vroonhof vroonhof@frege.math.ethz.ch ]现在虽然INND和朋友是Usenet软件包的重要组成部分,但新闻阅读器更为重要。 现在我会打99%的读者,如fi Gnus,假设标题中的地址是当用户要求与作者进行私人讨论时回复的地址(即回复而不是跟进)。

[marty] netnews是一个公共论坛。 邮件是私人通信媒体。 在公开论坛发帖并不要求我让你访问我的私人地址,就像在公开会议上发言不要求我给你我的不公开的电话号码。

有一点是肯定的:把任何人想要发送邮件给你的负担,要求他们破译地址。 有人可能永远不会通过邮件回复使用这些虚假地址的人。 任何希望发送个人邮件的人都不能打“回复”。 这样做的人接受这一点,他们将定期观看新闻组的跟进。 如果有人渴望获得个人信息,他可以花费额外的时间来破译该人的正确地址。 - 马蒂

不过,如果你不想给我你的电话号码,为什么要给我一个假的? 如果有这个愿望的人至少只能把他们的名字放在一边,而没有“<地址”部分,那么可以让新闻读者说“不可以回复,不给地址”。

[Counter argument,unknown]当我使用Pegasus Mail(Win95)时,花了我大约10分钟的时间来设置过滤器,这个过滤器已经超过我收到的垃圾邮件的75%。 10分钟对你来说太大了吗? 我,你是一个忙碌的人

[timothy]我没有控制的网络(网络在工作),我没有说什么软件安装在哪里? 我可以对系统管理员说“嘿,我想要安装飞马邮件”,他点点头,嘟les着一些东西。 他有两年的积压从没有一个真正的系统管理员周围

[Counter参数,未知]此外,网络上还提供了许多procmail配方,可以轻微调整以过滤邮件。 不需要重型Unix技能。 只是主动对自己的问题负责。

我知道procmail很好,垃圾邮件发送者仍在通过。 你知道为什么? 他们拒绝遵守我们依赖的所有惯例。 他们垃圾邮件列表,所以我也必须过滤。 我花了无数的时间尝试开发更好更好的过滤器,而且数量较少。 没有什么工作,没有给更多的垃圾邮件发送者我的地址。

...你只是宁愿将问题放在别人身上,而不是花时间自己处理。 那么这些懒惰似乎在这个“互联网世界”中占主导地位。

我花了时间,从别人所做的事情中学习,并寻求改善他们。 你肯定你是对的,拒绝再考虑它....而那种懒惰就在互联网上。

唯一一个错误的不便之处就是那些需要邮寄我并丢失邮件地址的人。 如果您想跟进Usenet的帖子,请在Usenet中进行。 我会回到这里跟进。 我收到足够的邮件,不需要Usenet线程的邮件。

如果你想让我使用一个真实的地址,请设置一个procmail的帐户,我可以得到我的所有Usenet相关的消息发送。 - 蒂莫西

21.2关于地址munging的评论

[1998-03-24 gnu.emacs.gnus drwho@No-Spam-see-sig.xnet.com ]

...我很清楚这是不好的行为,因为我很清楚它违反了标准。 不过,我很清楚,每次看完垃圾邮件时,我都不需要邮箱。 自从我开始改变我的“发件人”行以来,事情已经相当平静了。 尽管如此,偶尔也会得到我。 现在并不是这么大的事情,但是在跟踪网络滥用新闻组一段时间后,对我来说,垃圾邮件发送者正在尝试新的策略来抓取邮件地址(msg id,发件人:行等)... )。

由于我必须从POP3帐户下载我的大部分邮件,所以需要等待所有垃圾邮件下载的时间。 如果打破我的标题意味着得到和平与自由的垃圾邮件,那么就这样。

[M. 麦克斯韦drwho@No-Spam-see.sig 1998-03-26 gnus.emacs.gnus]

相信我,我喜欢这样做

在所有 但它却使我 相当恶化。 我也不必从POP3服务器(我的ISP有一个shell帐户)下载我的邮件,但我更喜欢读取邮件离线,因为我收到所有这些邮件列表,

既然如此,我最终下载了大量的垃圾邮件和合法的邮件,之后我的本地procmail把它放在它所属的地方。 换句话说,不在我的收件箱。 所以我会做我所要挫败的垃圾邮件发送者(直到我们得到一些通过垃圾邮件的立法)。 那些经过污垢头的那些被相应地处理。

21.3 RFC和有效的邮件地址字符

电子邮件地址中哪些字符合法? 到目前为止,我有大写,小写,数字_ _ +。 @

[elijah]大多数任何7位字符。 对于所有实际用途,空格(空格,制表符,换行符)真的不合适。 这个帖子来自一个有效的地址。 我也有一些控制字符 - 例如<@ qz.to>(可能不会出现在你的新闻阅读器中)。 有关生成地址的完整规则,请参见RFC822,但是快速而肮脏的事情是必须引用任何“特殊功能”。

      See definition of `specials' in RFC
specials = (),;:\.[] and a double quote

如果你不相信我,就有邮件玩具来证明这一点。 汤姆·菲尼克斯的“ fred&barney"@redcat.com”地址,我现在知道的最好的一个。 您可以使用我相信的任何字符串来替换“&”。 我已经尝试过像“ fred ($)barney"@redcat.com”这样的东西,看起来很稳定。

21.4 RFC和login-name @ fdqn

[1998-06-08 Message-ID: wkd8cjekay.fsf@mjf.vip.best.com Marty Fouts Usenet-user@usa.net在gnu.emacs.help。 请参阅1998-06-11消息ID: wk4sxs62ll.fsf@mjf.vip.best.com由Marty Fouts撰写的整篇主题摘要。]

      >>>>> In article <EM>x7g1hfu2sf.fsf@gkar.prescienttech.com</EM>,
>>>>> Rich Pieri <EM>rich.pieri@prescienttech.com</EM> enscribed:

> -----BEGIN PGP SIGNED MESSAGE-----

> Marty Fouts writes:

>> Sort of: system-name is not a hook into gethostbyname. The
>> /variable/ system-name is set by a builtin defvar to
>> gethostbyname. system-name returns the value of the /variable/
>> system-name, and the emacs lisp manual advises setting it if it
>> is not correct.

> It still uses gethostbyname() to set the initial value.
> gethostbyname() is supposed to return an fqdn on a networked
> host.

所以? 初始值为FQDN并不表示此后随时返回的值。 这就是为什么emacs不使用system-name创建邮件地址,而是具有单独的功能。 如果emacs本身不依赖系统名来生成任何邮件地址,为什么要gnus?

      >>> user@fqdn is the agent responsible for submission of a
>>> message to the network. user@fqdn is the RFC sender of the
>>> message. user@fqdn therefore must be made to be a valid
>>> mailbox.

>> This is just flat out wrong. There is no such requirement in
>> any RFC or implied by any combination of RFCs.

> Premise: Gnus is used interactively. Premise: "user"
> (user-login-name) is the login name of the person using Gnus.

那就是你失败的地方。 在任何RFC或RFC的组合中,任何一个登录名甚至不存在任何要求。 虽然你的前提是真实的,但这与你的结论无关,如下所述。

      > Premise: "fqdn" (system-name, self-referential gethostbyname) is
> the canonical network host name of the machine "user" is using at
> the time.

那就是你失败的地方。 机器“用户”正在使用的RFC或组合的RFC中的任何地方都不需要作为邮箱的一部分进行暴露。 我/允许/做这个,如果我这样做,我需要支持该邮箱是有效的。 我不是 /需要/做到这一点。

我已经引用并且将重复说,TIP是这样的机器的一个很好的例子。 POP3客户端也是如此。 您缺少一些更多的前提,最值得注意的是,user @ fqdn是RFC或RFC的组合意义上的消息发送者

最重要的是,您在逻辑中缺少一些步骤。

  • 您还没有确定/ sender / field的邮箱必须是您将从user-login-name @ system-name构造的邮箱,即使在组合形成有效邮箱的系统上也是如此。
  • 您尚未建立用户登录名@系统名称来形成有效的邮箱,即使系统具有登录名的概念,并且user-login-name和system-name都返回您期望的内容至。

因为没有这样的要求,你也不能。

  • 在RFC的任何组合中有/ no / requirements / anywhere / any /可以从任何类型的“登录名”和FQDN的组合构建邮箱。
  • 在“登录名”甚至存在的RFC的任何组合中都有/ no / requirements / anywhere / any /。
  • 对于“登录名”的概念,RFC的任何组合都有/ no / definition / anywhere / any。

尽可能简单地说:

您不确定是否要求系统支持(login-name,FQDN)到login-name @ FQDN形式的邮箱的映射。

一旦你明白这个断言是不正确的,应该很容易看出从它派生的所有断言是不正确的。

21.5 RFC和消息签名

http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html

根据通用的defacto网络约定,签名前必须有“\ n-- \ n”。 签名分隔符中的额外空间指示它是用户的消息,而不是使用分隔符“\ n - \ n”的消息摘要。 没有可以解决这个问题的RFC。

顺便说一下,长达1-3行的时间是不礼貌的。 更好的是,如果您的MUA支持修改标题,请将重复的信息移动到X标头。

注意 :分隔符的选择有点不幸,因为它依赖于保留尾随的空格,但是它是太完善的改变。

[Paul O.Bartlett pobart@access.digex.net ]例如 当写入文本时,首选的Un * x编辑器在编写文件时会定期截断尾随空格,这样即使签名中有“ - ”,Pine也可以自动将其作为可编辑的文本的一部分
文本,编辑器将简单地截断空白。 签名分隔符可能“太完善,不能改变”,但它与人们使用的工具的现实相冲突。

21.6 RFC并在Usenet新闻组中使用MIME

[1999-02-12 Marty Fouts gnus @ .fogey.com in gnu.emacs.gnus Message-id: wklni3b3gl.fsf@Usenet.nospam.fogey.com ]

使用MIME是有争议的。 在USENET发布中使用MIME是不可原谅的,除了草案中涵盖的情况除外:

由于有权力(通过共同同意或其他方式)授权在各层次,新闻组或合作子网中界定什么是不合适的,那么这些权力机构应该通过规则,准则,章程或其他方式来建立实践被认为是可以接受的。 特别是他们应该确定哪些更异国情调的内容类型可能不合适。 在没有具体指导的情况下,提供以下默认建议作为当前最佳做法的指示。

请注意,评论“不可原谅”是我的意见。 草案与您明显的理解相反,只是给出了指导 - 如何使用mime标头。

如果您或任何其他人认为RFC 1036的替代草案需要不同的措辞,欢迎您加入该工作组,并试图说服其成员。 然而,一个警告是有序的:这个过程已经持续了几年,截止日期的方法,这个特定的问题已经被很多细节的争论了。

21.7一些RFC指针

http://www.cis.ohio-state.edu/hypertext/information/rfc.html
  • rfc821 SMTP协议,另见rfc959 FTP协议标准
  • rfc822网络邮件的格式(以前称为Arpanet)可能取代822的新草稿位于: ftp : //ftp.ietf.org/internet-drafts/draft-ietf-drums-msg-fmt-04.txt
  • rfc1036(邮件格式标准:从,到,日期...)检查前面提到的-1036.html的son-of 。
  • rfc1153摘要消息格式,1990,状态:实验)
  • rfc1738 URL规范,mailto,http,<URL:address>请咨询rfc2396,取代rfc1738。 <URL:...>包装已被人气需求推翻。 “为所有URI定义一个单一的通用语法”。 另请参见rfc2369“将URL用作核心邮件列表命令的元语法”
  • rfc1855网路指南1995
  • rfc1991 PGP消息交换格式
  • rfc2076常见的Internet消息头
  • rfc2045,6,7 MIME
  • rfc2111 Content-ID和Message-ID统一资源定位器也是rfc1341
  • rfc2142常用服务,角色和功能的邮箱名称

更多细节

22.0电子邮件标题简介

22.1要了解有关邮件(资源)的更多信息

关于电子邮件标题
http://www.stopspam.org/email/headers/headers.html ...本文档旨在全面介绍邮件头的行为。 它主要是为了帮助未经请求的邮件(“邮件垃圾邮件”)的受害者试图确定(通常是伪造的)邮件的真正来源; 它也应该有助于尝试了解任何其他伪造的邮件。 对在互联网上传送邮件的通用介绍感兴趣的读者也可能是有益的。

[参见RFC部分中的RFC指针]

IMC - 互联网邮件标准
http://www.imc.org/mail-standards.html

常见问题归档
http://www.FAQs.org/FAQs/

RTFM ftp存档 - 阅读精细手册
ftp://rtfm.mit.edu/pub/Usenet-by-hierarchy/comp/mail/

发送邮件
顶部“> ftp://rtfm.mit.edu/pub/Usenet-by-group/comp.mail.misc/sendmail常见问题

UNIX电子邮件软件
http://www.faqs.org/faqs/mail/setup/unix/part1/index.html ...本文档适用于需要知道如何设置其UNIX系统以与外部进行邮件通信的系统管理员世界... UUCP,地址,域名,FQDN,NIC,MX记录,Bang-Paths,网关,路由器,Smarthost,MIME,X.400,“地图”,别名

加寻址
http://www.FAQs.org/FAQs/mail/addressing/

了解电子邮件地址,DNS,网关
http://www.uiuc.edu/uiucnet/3-2-1.html

Unix MBOX,Berkeley格式
http://www.qmail.org/qmail-manual-html/man5/mbox.html ...这种格式来自我们从古老的UNIX邮件程序V7 /bin/mail...Each消息以两个空白结尾线条

[1998-09-06 PM-L Dallman Ross dman@netcom.com ]我认为与伯克利的联系是/ usr / ucb / mail(又名“邮件”,资本“M”); 不是/ usr / bin / mail(又名“/ bin / mail”)。 (“UCB”代表“加利福尼亚大学伯克利分校”)。两者相近,尽管如此,如果我尝试使用/ bin / 但是“古UNIX邮件程序”? 我使用并喜欢/ usr / ucb / mail,只要我在一个UNIX外壳。 许多其他人也这样做。 <Yeesh>(我不喜欢松树,感觉也是GUI。)

好的,对不起,你们都谈论RFC和From_线。 如果它被称为“伯克利邮件格式”,那么我将推断它来自伯克利邮件。

文学
鲍勃博士无线指南互联网:您可以用电子邮件做的惊人的事情鲍勃Rankin No Starch新闻ISBN:1886411093标价:$ 12.95

Netiquette by Virginia Shea平装本1版(1994年5月)Albion Books ISBN:0963702513 Amazon.com价格:$ 19.95

电子邮件的元素:通过电子邮件有效地通过电子邮件通过David Angell,Brent D. Heslop Addison-Wesley Pub Co(C)ISBN:0201627094平装 - 157页(1994年4月)标价:$ 12.95

所有关于互联网邮件(互联网研讨会系列,第7号)由李大卫杰夫图书馆解决方案Inst&Pr ISBN:188220820X Amazon.com价格:$ 34.00

3 Rs电子邮件:风险,权利和责任Diane B. Hartman,Karen S. Nantz Crisp Publications Inc. ISBN:1560523786平装 - 153页(1996年6月)标价:$ 12.95

电子邮件伴侣; 通过互联网和其他全球网络有效沟通John S. Quarterman,Smoot Carl-Mitchell Addison Wesley Pub Co ISBN:0201406586平装本 - 318页(1994年11月)标价:$ 19.95

互联网讯息:马歇尔T.罗斯Prentice霍尔(Sd)电子邮件关闭书(缺货)ISBN:0130929417

管理邮件列表:Majordomo,LISTSERV,ListProc和SmartList作者:Alan Schwartz O'Reilly&Assoc。 第一版1998年3月ISBN:1-56592-259-X 298页,$ 29.95 http://www.oreilly.com/catalog/mailing/

sendmail,第2版由Bryan Costales和Eric Allman O'Reilly&Assoc。 2nd Edition January 1997 ISBN:1-56592-222-0 1050 pages,$ 39.95 < http://www.oreilly.com/ >

22.2 Alan Stebbens讲座

<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/ cgi-bin / w3glimpse2HTML / procmail / 1996-08 / msg00098.html?69#mfs>

标头有两个通用类别:由MTA自动生成的,以及由MUA配置和插入的用户。

前者,由MTA生成的,主要用于跟踪电子邮件,通常与邮件的内容无关,就像FedEx用于跟踪包的条形码标签一样。

后者,由MUA或用户插入的,就像FedEx客户填写的运输标签,即:它们确定来源,目的地和描述邮件的内容。

用户自己生成所有这些MUA头​​是太麻烦了,所以用户的邮件程序会自动生成许多或大部分的邮件,通常在配置控制下。 当然,用户可以随时覆盖或替换自动MUA头。

另一方面,MTA标头几乎是完全自动的,用户几乎从不改变它们。 只有在特殊情况下,用户才能插入或修改MTA标头。

然而,从用户的角度来看,电子邮件过程似乎是原子的,所以这些头类的区别就会丢失。 即使一些系统管理员或后台管理员也不了解它在电子邮件过程的不同阶段,插入不同的标题集。

为了帮助澄清这个区别,以下是电子邮件过程及其几个阶段的图表:

      sender -> MUA -> MTA ->..-> MTA -> MDA ->{maildrop}-> MUA -> reader
[1] [2] [3] [4] [5] [6]

标题通常由MUA的“模板”提供给发送者,通常在阶段[1](撰写电子邮件时):

      From:               # who I am
To: # the target
Cc: # people to keep informed, but need not respond
Bcc: # secret admirers
Subject: # what's the mail about
Reply-To: # highest priority return address
Priority:
Precedence:
Resent-To: # used for redirecting e-mail
Resent-Cc:
X-BlahBlah: # personalized headers

当发件人完成撰写,并将其发送给他/她的邮件时,MUA在此阶段可能会插入一些额外的标题[2]:

      Date:
Resent-Date: # if being redirected
From: # If not already present
Sender: # if a From: is already present
X-Mailer: # what MUA composed this message
Mime-Version:
Content-Type: # what kind of stuff is in here
Content-Transfer-Encoding:
Content-Length:

当MTA在[3]阶段从MUA收到电子邮件时,可能会插入附加标题,显示电子邮件的发起:

      From                # if local e-mail, automatic or by -f option
Date # If not already present
Message-Id: # unique ID for the e-mail; the first MTA
# creates this
Received: # shows inter-system e-mail tracking info
Return-Path: # shows how to get back to the sender

由于每个MTA都会关闭电子邮件,所以在[3]阶段,可能会添加额外的头文件,这些标题全部作为MTA切换的一部分:

      Received:           # inserted by each MTA

由于最终的MTA将电子邮件转交给代理(MDA),在[4]阶段,仍然可能会出现一些更多的标题插入:

      Apparently-To:      # added if no To: header exists
From # may get added if local e-mail

一些网站插入特殊的重写规则和过滤以支持虚拟域,这些标题更改将在[5]阶段发生,就在接收邮件被丢弃之前。 通常,尽管没有添加新的头文件,除了可以避免循环之外:

      X-Loop: $USER@$HOST # inserted to avoid filtering loops

最后,在阶段[6],当读者查看他/她的电子邮件时,大多数MUA将对存储的邮件应用过滤器,导致从显示器中省略所选的标题。 从某种意义上讲,这种过滤从用户的角度“删除”头文件(尽管MUA实际上没有头文件)。

通常省略的标头是由MTA插入的标头,以及与传输过程有关的标题,而与内容相关的标题较少。

22.3应用于收到的消息

[alan]所以,现在我们有一个共同的理解...

第一个“From”是一个Unix-mail From_头(注意空格)。 这是由MTA自动插入,除非已经存在,并且只有在似乎有效的情况下。

第二个From:由MUA(您的个人邮件程序)生成,无论是通过配置还是由用户生成。 sendmail和大多数过滤程序中的重写规则都关注From: , To: , Cc: , Reply-To: headers。

我会假设,如果“From smmi”不是“正确的”,那么你必须试图隐藏交付过程,并实现一些虚拟域。

一般来说,“纠正”MTA插入的自动邮件标题是一个坏主意。 这是改变显示虚拟域的地址的另一个问题。 From_头是邮件历史的一部分,显示邮件的发起方式。 类似地,“Received:”标题不应该被弄乱。 更改电子邮件的历史将使得很难诊断电子邮件传送错误。

话虽如此,既然我也相信选择的自由,我现在将为你提供“足够的绳子来挂自己”:^)

有两个地方可以使From_标题更正:在它被放入邮箱(用于收到的电子邮件)之前,或者它被提交到MTA(用于传出电子邮件)。

在删除之前更改From_很容易。 只需使用这样的Recipe:

      FROM    = `$FORMAIL -zxFrom:`
DATE = ...construct the RFC date format

:0 fhw
| $FORMAIL -I "From $FROM $DATE"

当收件人邮件收到邮件时,MTA(sendmail)会自动创建From_头文件。 如果通过sendmail发送邮件而不使用'-f'选项,则sendmail会将默认的From_设置为当前用户的默认值。 如果您不是root用户,或者是“受信任的用户”(请参阅​​sendmail手册页),则sendmail将忽略From_头文件,并将其全部删除或替换。 即使您是root用户,如果在本地接收电子邮件(而不是网络),则sendmail将替换From_ 。

如果要更改From_ ,则必须以root或“受信任用户”的形式调用sendmail,并使用“-f”选项。 EG:要设置From_以匹配From:头,请使用以下配方:root:

      :0 h
FROM=|$FORMAIL -zxFrom:

:0
! -oi -t -f"$FROM"

请阅读sendmail上的手册页,注意使用'-f'。

22.4 Alan Stebbens的Bcc讲座

< http://www.rosat.mpe-garching.mpg.de/mailing-lists/procmail/1996-11/msg00054.html >

Procmail最典型地处理目的地站点的传入邮件; BCC格式化(或缺少)是在外发邮件,始发站点完成的。

对于这个讨论,让我们对邮件的种类进行区分:(a)收到的邮件,和(b)外发邮件。 Bcc被用户插入到外发邮件中,然后将消息交给MUA。 然后,MUA可以处理BCC或延迟到邮件传输代理(MTA),例如sendmail。 无论哪个代理执行Bcc功能,该功能至少以三种不同的方式执行:

  • 许多MUA格式化没有Bcc:头的传出邮件,以便将相同的消息头发送给所有收件人。 密件抄送:收件人在邮件正文中收到一个额外的行,表示邮件的性质。 消息的文本从MUA到MUA不同; Rand Mailer,MH,例如在原始文本中插入行:

      ------- Blind-Carbon-Copy
...
------- End of Blind-Carbon-Copy
  • 一些MUA将单独发送消息给每个密件抄送:收件人,收件人地址在Bcc:标头上。 因此,每个Bcc接收方知道他们通过密件抄送方式收到该邮件,但不知道其他的是密件抄送者。 所有密件抄送者都是私人的,甚至是其他密件抄送者。 (如果所有MUAs都以这种方式行事,会很好)。
  • 几个MUAs传递消息没有密件抄送:,但没有任何特殊的指示; 你必须猜到这是一个密尔。

原始邮件标准RFC822对此表示了关于Bcc:

4.5.3。 BCC / RESENT-BCC

此字段包含消息的其他收件人的身份。 此字段的内容不包括在发送到主要和次要收件人的邮件的副本中。 一些系统可以选择仅在作者的副本中包括“密件抄送”字段的文本,而其他系统也可以将其发送到发送给“密件抄送”列表中指示的所有人的文本。

因此,如果发件人的MUA在头文件中包含密件抄送,procmail 正确处理密件抄送。 但是,由于procmail最常用于传入邮件,所以它永远不会有机会处理Bcc:头文件。

22.5由Philip Guenther发表的Bcc讲座

<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/procmail/1996-11/msg00055.html >

通常,Bcc:标头不会出现在传入的消息中(如果procmail用于处理可能发生的传出邮件)。 大多数(?)邮件用户代理将通过完全删除标题并将地址放在信封收件人列表中,并从To:和Cc:headers中的其他收件人发送bcc。 以这种方式,邮件被封锁的地址*不会出现在标题的所有*,而您是SOL。

在procmail运行时(在标准安装中),信封丢失,这是您能够以任何可能的规律处理密件抄送的唯一方法,即使是怀疑在另一个站点包含您的地址的别名被封杀,那么信封到达你的网站时,只会包含你的(本地)地址。

此外,Bcc:header的全部内容是接收消息的人不知道消息发送到的地址的整个列表。 如果一个别名被封锁,还不清楚别名的成员是否应该知道这是别名,而不仅仅是个人。

必须跟随电子邮件一起旅行的BCC目的地。 否则,它如何知道它的目的地? 如果我是对的,那么无法procmail使用这个来正确处理消息?

[阿兰]

<URL: http : //www.rosat.mpe-garching.mpg.de/mailing-lists/procmail/ 1996-11 / msg00093.html>

只有MTA知道目的地址,因为它是“信封”的一部分,这是在“RCPT To:some-user”SMTP行上传递的信息。 这些信息是MTA如何知道传递邮件,而不是标题的内容。

当然,当正确调用时,许多MTA可以读取头部以获得随后的SMTP连接中后续“RCPT”命令所需的地址。 实际上,Bcc:头可以与其余的目标头一起读取,以获取收件人地址,但是还将从头文件中删除密件抄送:。

MTA接收邮件的地址被称为“信封地址”,它可能与消息本身中的任何标题不同,或者与其中一个相同,用于直接寻址的邮件。

例如,通过邮件列表,收件人将永远不会看到他/她自己的地址,但会看到To:或Cc:头域中的邮件列表。 即使在这里,当邮件发送到多个邮件列表时,还没有确定接收到邮件地址的标准。 有许多约定遵循,启发式,但没有明确的标准来表明交付的原因。

您可以配置您的MTA在新的标题中传递信封,或通过参数传递给本地传递程序(可以是procmail)。 然后由本地交付程序使用(或不)包络地址信息。

如果您想了解邮件系统的限制,应阅读RFC822(邮件格式化标准)和RFC821,该标准描述了SMTP的原始语言。 有几个扩展正在进行,但是“MAIL”,“RCPT”和“DATA”的基本命令就足够了。

23.0消息头

23.1什么是正确地址语法

案例1是RFC 822中的内容,我记得。 我将案例2视为“屏幕语法”,以便包含在纯文本消息体上下文中。 它可以用于标题的交互式呈现,但是我会倾向于认为任何不接受原始RFC-822表单的工具都被破坏。

      1. login@path.to.host (Personal Name)
2. Personal Name <EM>login@path.to.host</EM>

[1998-05-31 FAQ-L Simon Lyall simon@darkmere.gen.nz ]这两种形式都是合法的,但是新闻和标准文件的进行方式是第一种形式不鼓励。 这有效地意味着软件应该接受这两种形式,但只能生成第二种形式(这是文章首先不是由世界各地的人创建的)。

第一种形式的问题是括号中的内容实际上是“评论”,而不是海报的名称。 这意味着没有办法使用第一种形式来实际说出你的名字,只是大多数人在评论栏里说出自己的名字。 他们可以很容易地说出别的话。 这意味着将该注释字段显示为该名称的软件只是猜测。

第二种格式将发布的名称放在软件可以使用的确定位置,并允许您将括号用于评论。 关于这一点的当前互联网草案在这一点上最有可能取代RFC 822的是:

      ftp://ftp.ietf.org/internet-drafts/draft-ietf-drums-msg-fmt-04.txt

有点是第3.4节说:

注意:一些传统实现使用的是addr-spec没有尖括号的简单形式,但是在addr-spec之后,将括号中的收件人的名称作为注释。 由于注释中的信息的含义未指定,如果正在使用收件人的名称而不是旧表单,那么实现应该使用邮箱的全名添加器形式。 另外,由于一些传统实现解释了注释,注释通常不能用于地址字段以避免混淆。

23.2什么是X-UIDL标题?

[philip]
  • 它不是标准化的,并且将永远不会被RFC标准化。 (没有X-标题可以)
  • 一些服务器使用它来存储UIDL命令的信息。
  • 一些客户端显然在本地下载的副本的这个头文件中存储UIDL信息。 (注意:POP3协议不允许客户端修改存储在服务器上的消息。)
  • 一些垃圾邮件软件包在发送的消息中包含此标题,以使一些支持客户端过滤的POP3客户端认为已经过滤了消息。
  • 过滤掉传入的邮件(通过POP3预先检索)似乎是“公平的”安全的,尽管一些合法邮件可能包含这个标题。 使用它作为重量级(但不够自己)在procmail评分Recipe检测垃圾邮件似乎是合理的。
  • [philip]如果一个消息进入您的邮箱有X-UIDL:标题,并没有你的地址在标题,那么我会对它的合法性有很大的怀疑。
  • [ed]评论:与X-UIDL的电子邮件:标题几乎绝对是垃圾邮件,除非他们已经被Resent-To:我被某人。 此外,有效的X-UIDL:标头具有32位十六进制数字。

[David]最近在procmail列表中讨论了使用X-UIDL:头文件清除所有邮件的可行性; 显然有可能出现在合法邮件中。

[以利亚] 非常真实 很可能的情况可能是某些类型的转发邮件,包括一些主持人的邮件列表。 Fluffy的mod * *列表有这些,直到我向Fluffy指出了广泛的文件到/ dev / null问题。

23.3什么是第一个From_头?

[philip] From_行上的地址是信封发件人。 如果消息有一个Return-Path:头,那么可能会更容易使用,因为那样你就不需要处理在 From_头的末尾找到的日期。

不要使用信息来设置信封。 消息中的标头允许包含与To:和Cc:头中的地址列表,这些消息与消息的位置完全无关。 例如,来自邮寄名单的邮件可能简单地说“To:procmail@Informatik.RWTH-Aachen.DE”,没有可见的迹象表示“guenther@gac.edu”是要传送邮件的地址。 信息当前正在传送到的信息只能在信封中找到。

好的,这个珍贵的信封在哪里? 在SMTP中,信封由MAIL FROM:和RCPT TO:SMTP命令组成。 但是,当向本地邮件程序发送消息时,通常会丢失该信息。 那么信封发件人通常在Return-Path:头中保存几天,但信封收件人通常只会以登录名的形式显示本地邮件程序在命令行上传递。 例如,可以使用/ etc / procmailrc脚本来检查$ LOGNAME以查看消息设置的位置。

当人们开始创建虚拟域时,会出现问题。 当sendmail执行别名(通常是通过mailertable我相信?),它完全失去原始的信封收件人地址在重写。 所有的地址都被重写为同一个东西,因此sendmail没有任何区别的地方。 失去独立身份后,现在相同的多个收件人被合并,以形成一个本地邮件的呼叫。

这里的关键在于,一旦信封收件人被虚拟域别名丢失,就不用担心了! 您可以挥手,尝试伪造它,但虚拟域中的任何人都不能访问邮件列表,或以其他方式收到一封邮件,其中邮件头不明确地包含他/她的邮件地址。 此外,即使这样做,伪装也是非常困难的。 下面显示的内容不正确地处理使用Resent- *标头的消息。 这可能导致不应收到他们的人收到的消息,可能违反某人的隐私。 如果你决定使用它,请记住这一点。 它处理了很大比例的案例,但会在将来的某个时刻咬死你。

所以你可能会问,这是否意味着虚拟域是无望的? 答案是否定的,您只需要在sendmail.cf中非常小心,将信封接收者置于足够长的地方,将其作为参数传递给本地邮件程序,通常将其放入“主机”部分邮件三重版,尽管与sendmail 8.7.x,把它放在本地的一个“+”可能是非常干净的。 最后,它最终被传递给procmail(标准/ bin / mail没有办法处理这个,但我们已经知道)作为另一个参数(即,一个orig-envelope-recip),尽管有一些工作可能有可能通过一个新的标题来做到这一点,但是这是比较糟糕的,没有效率。 我没有必要的sendmail.cf(或m4 .mc)mods这样做,但如果你发布到comp.mail.sendmail(在检查FAQ之后,我认为它可能在那里)有人可能会给您进一步指出在虚拟域中保存信封收件人的情况。

23.4消息标识头

...使用非法MessageID的“有效”邮件有问题吗? 由于某些奇怪的原因,有些人正在发送带有不良消息ID的邮件。 这不是什么大问题,除了我们的MITS部门甚至不会考虑修复bad-message-id,除非在其他地方造成问题。

为什么他们不考虑修复它? 他们的电子邮件软件/网关坏了,需要修复。 就是这样。 将它们引导到RFC 822,第4.6.1节。 http://www.ietf.org/rfc/rfc0822.txt?number=822

[Gerald Oskoboiny gerald@impressive.net ]有一些问题,邮件的一些问题包含一个不良的邮件标识

有些人(包括我自己)运行过滤器,以便如果最近看到其邮件ID,或者看起来很虚伪,则自动删除传入的电子邮件。

某些邮件列表软件(包括Smartlist)不接受最近看到的邮件ID的电子邮件。 每条消息必须具有唯一的消息ID。 在全局环境中确保msgid是唯一的最佳方式是在'@'之后添加一个完全限定域名。 特别地,像<3.0.5.32.19971208192547.007db100@mailhub>这样的消息ID是不可接受的(即使在最后没有空格)。

某些邮件归档软件(包括我写的一些)使用消息ID作为归档中该消息的唯一标识符。 它可能会拒绝看起来是重复的邮件,因为他们有其他邮件使用的邮件ID。 (就像我的软件一样)

[生成消息id]

[不锈钢大鼠ratinox@peorth.gweep.net 1998-03-13在Emacs Gnus邮件列表] ...强烈建议Message-Id字符串由MUA而不是MTA生成。 原因是邮件中心可以同时处理多个消息(多个CPU),因此可能会意外生成重复的Message-Id字符串。 只有当MUA愚蠢而无法做到时,MTA应该生成Message-Id头。

[phil 1998-03-19 PM-L] ...让我们快速完成一个更完整的正则表达式来匹配Message-Id 。 我将从rfc822采用符合它们的正则表达式的语法行。 为了便于介绍,我将从下到上工作。 注意:只包含空格的任何括号应该真的包含空格和制表符。

      dq         = '"'                        # (literal) double-quote
bw = "\\" # (literal) backwhack
ws = "[ ]*" # whitespace
atom = "[-!#-'*+/-9=?A-Z^-~]+"
word = "($atom|$dq([^$dq\]|$bw.)*$dq)'
local_part = "$word($ws\.$ws$word)*"
domain = "(\[$ws([^][\]|$bw.)*$ws\]|$atom($ws\.$ws$atom)*)"

:0
*$ ! ^Message-Id:$ws<EM>$ws$local_part$ws@$ws$domain$ws</EM>
{
...Catched illegal message id
}

...我已经开始记录符合条件的ids。 它匹配了两个消息到目前为止。 一个消息ID显然是虚假的,但是另一个消息ID(其中一个是邮件列表,每周1 msg,没有垃圾邮件):

      Message-Id: <199803251729.LAA10847@wuarchive.wustl.edu.>

您的正则表达式不完整wrt是否在域名部分拖尾,还是MUA / MTA损坏?

[philip] rfc822不允许拖尾点。 我刚刚看了新的互联网消息标头标准草案(最终替换了rfc822),也没有。 相反,它进一步限制生成的Message-Id头的语法,以禁止注释或折叠空格发生在消息id本身中。

但是 ,在您收紧正则表达式之前,请注意,该标准要求处理消息的程序必须接受并解析符合过时语法的消息。 这是因为旧的邮件可以长时间挂起,大部分其他互联网数据格式看不到。 新的要求是生成新消息,而不是旧消息。

[1998-10-22 comp.emacs Toby Speight Toby.Speight@digitivity.com ]

通过Message-ID引用新闻文章(这就是Message-ID的功能)更为常用(有用)!)。 在这种情况下

      <URL:>

如果你喜欢DejaNews:

      <URL:http://search.dejanews.com/msgid.xp?MID=%3C
uhfwwk9ae.fsf_-_@delivery.ansa.co.uk%3E&fmt=raw>

(虽然由于某些原因,这返回文本/简单的东西,这显然是一个消息/ rfc822)。 任何一个都是一个明确的URL,不受时间相关的更改的影响。 网址设计完全是为了消除对这些描述的需要。

23.5收到标题

...找到另一个有趣的模式,Received标题都在一行。 通常一个Received:标题跨越两行,至少在我收到的所有邮件上。 此过滤器查找单行Received:标题和陷阱:

      :0:
*Received:\/( ?[^ ])*$
mail/Spam

[Christopher Lindsey lindsey@ncsa.uiuc.edu ]没有保证。 我刚刚尝试了一些测试邮箱(都知道有有效的邮件),它匹配像疯了。 据我所知,RFC 822对Received标头中的多行没有要求。

[Reto Lichtensteiger rali@meitca.com ] sendmail中配置了一行头文件与多行头文件:一个较旧的cf文件(V8.7):

      HReceived: $?sfrom $s $.$?_($?s$|from $.$_) \
$.by $j ($v/$Z)$?r with $r$. id $i$?u for $u$.; $b

稍后(V8.8)之一:

      HReceived: $?sfrom $s $.$?_($?s$|from $.$_)
$.by $j ($v/$Z)$?r with $r$. id $i$?u
for $u; $|;
$.$b

23.6返回路径

...我创建了一个带有.forward和procmailrc文件的用户(lo_mailer),将传入的邮件传输到正确的用户。
这很正常,但是Return-Path:Line设置为本地procmail用户(lo_mailer),并且不包含原始的Return-Path! 我能做些什么来赢回原来的线? 请帮帮我 :)

[david]通常当你转发邮件时,你不应该保留原来的返回路径。 如果转发目的地无效或无法访问,则必须将邮件返回给转发器,谁可以修复转发例程,而不是原始发件人,谁不能做任何事情,甚至从来没有听说过最终的目的地址。

但是,尽管您应该更改返回路径,但不必丢失原始返回路径所包含的信息。 你可以安全地将它放入身体或另一个标题行。 在lo_mailer的.procmailrc中尝试这样做:

      :0fwh # if there's a return path, save it as Old-Return-Path:
* ^Return-Path:.*<.+>
| formail -iReturn-Path: # lower-case i

:0Efwh # if there's no return path but there is a From_, use that
* ^^From[ ]+\/[^ ]+
| formail -A "Old-Return-Path: <$MATCH>"

:0Efwh # if there was neither a Return-Path: nor a From_
| formail -A "Old-Return-Path: unknown"

在第二个配方的条件线中的第一组括号中包含空格和制表符; 第二组包含插入符号,空格,标签。

在从lo_mailer到最终收件人的转发站点上,返回路径将是lo_mailer,因为它应该是,但是如果最终的收件人想知道它在哪里发起,他或她可以看看Old-Return-Path头。

这里有一个警告。 如果lo_mailer将邮件发送到一般响应地址,并根据主题或正文内容将其分发给特定人员,或者通过旋转来平衡工作量,则可以使用。 但是,如果您有一个个人域名,并且您的ISP将您的域中的任何地址的所有邮件路由到您的ISP上的帐户,并且您依靠procmail将其传递到您自己的域中的正确地址,方法是阅读To:或Cc:标题,这是错误的方法。 正确的收件人将在信封上,在procmail可以看到之前从邮件中删除。 您的ISP必须执行某些操作,让您知道消息的真实信封收件人或收件人,而这里的其他人比我更了解更多信息(而且,我们可以告诉您的方式不会造成错误)。

[1998-11-11 Gnus-L Karl Kleinpaste]关于返回路径的标准,RFC822认为它应该是回到发起者的路由 ,即它应该显示中继跳; RFC1123反过来说,故障通知应该被发回到发起者,路由信息被删除,即“如果地址是明确的源路由,它应该被删除到最后一跳”。 ??? 那么首先提供源路由的要点是什么?

在我看来,返回路径的价值在源路由邮件被大量弃用的环境中已经变得非常有限,并且很少有人支持。 我知道,在几年前我做过严重的sendmail工作的时候,我拍摄了所有的源路由。

你可以用user-mail-address替换在sendmail中使用user-login-name的“-f”参数; 结果应该给出你需要的效果,而不是创建任何互操作性问题 - 邮件仍然会显示一个正确的方式返回给你。

也就是说,这个邮件列表对Return-Path的匹配要求确实很奇特。

23.7错误

1)有人可以确认错误:已被弃用吗? 2)是否有RFC?

[1998-09-15 Liviu Daia daia@stoilow.imar.ro ] 1)这是一个UUCP的东西,它的确是不赞成的。 这是sendmail手册中的相关报价。 2)可能不是,由于UUCP相关RFC尚未更新。

如果在处理过程中发生任何错误,该标题将导致错误消息转到列出的地址。 这是用于邮件列表。 错误到:标题已被正式弃用,并将在将来的版本中消失。

23.8 X-Subscription-Info

这是一些邮件列表使用的标题:它包含用于取消/订阅的邮件地址,或包含所述信息的URL。 想象一下减少bozo消息,询问如何取消订阅邮件列表。 如果您的邮件列表还没有,请向列表的维护者提出建议。

23.9回复标题

回复的存在意味着:“如果您回复我,将其发送到此地址而不是发件人:标题中的那个。”

在邮件列表的情况下,列表通常是该默认邮箱。 在这种情况下,“回覆”标题表示“不要将其发送到列表,而是将其发送到此处”。 再次,这又是一个“做我的意思”的问题。

ListAdmin:不要用回复播放
http://www.unicom.com/pw/reply-to-harmful.html ... RFC-822在回复中几乎没有希望。 人们做他们所做的事情更有可能是因为他们看到有人在做这件事,而且想像它是正确的,并被复制 - 也许稍微改变了一些事情。 ...如果您使用合理的邮件程序,“回覆”功能不会提供任何新功能。 实际上,它降低了功能。 回复To ing ing ing dest。。。。。。。。。。 能力。

回复问题
http://www.cs.utk.edu/~moore/reply-problem-list.txt

邮件跟进
ftp://koobera.math.uic.edu/www/proto/replyto.html ...这些标题可以做到有用的事情。 例如,在邮件列表中,假设所有帖子都被订阅(像这样),listserv可以添加一个“Mail-Followup-To:ding@gnus.org”标题。 发件人也可以使用它来表示“我订阅列表,不要我或其他人”。

[邮件 跟踪 问题] Keith Moore moore@cs.utk.edu Wed,11 Feb 1998 14:20:25 -0500对nmh列表发表了评论。 Keith是IETF应用领域的总监,曾任DRUMS工作组主席。

请不要在nmh中实现Mail-Reply-To和Mail-Followup-To的支持。 它们不仅不标准,而且对于这个问题来说是一个很差的解决方案。

回复被广泛误解为在回复中替换“发件人”字段,以“回复所有”的方式转到“回复”+“收件人”,如果回覆存在,则从+到+ CC,如果没有回复 - 到现场。

RFC 822具有似乎支持该视图的语言。 但是,仔细阅读RFC 822可以看出,这个散文不适用于“回覆全部”功能的回复方式,但只适用于“回复作者”功能中的回复方式。

这使我们了解消息的作者无法指定回复的完整目的地的情况。 即使作者指定了回复字段,如果收件人使用“全部回复”,仍然包括来自“收件人”和“CC”字段的地址。 这是几乎每个UA都存在的行为,但这几乎总是错误的。

RFC 822的例子清楚地表明,Reply-To旨在作为回复的完整目的地,而不仅仅是替换From字段。

解决这个问题的正确方法是正确解释“答复” - 而不是简单地替换回复中的“发件人”字段,而是作为主题消息的作者优选的回复目的地。 添加新标题无法解决问题。 这只会使情况更加复杂。

丹的提案本质上是有缺陷的。 它错误地假设发件人可以合理地预测收件人在回复邮件时的需求,并且这种需求可以合理地集中在“回复”或“跟进”中。 它并没有解决真正的问题,反应者需要考虑他们的答复。 邮件跟踪 - 不会减少到错误地方的邮件数量。

如果我发出一个邀请人参加会议的消息,想要“正常”的答复(大概是接受或拒绝邀请)去我的秘书。 我应该把我的秘书的地址放在“邮件回复”或“邮件跟进”?

说我把它放在邮件回复中,一个回复者想要发送一个个人的回复给我,也许是因为它是敏感的。 所以他点击“回复作者”,认为这个消息会发给我。 相反,消息传给我的秘书。 这不好。

说我把我的秘书的地址放在Mail-Followup-To中,一个响应者想要发送消息给原始消息的收件人列表 - 也许应答者想让每个人都知道便宜的机票到会议。 所以响应者点击“回复每个人”,认为这个消息会发送给大家。 相反,消息传给我的秘书。 这并不像其他情况那样糟糕,但仍然是不可取的。

所以如果一些答复既不是“个人”也不是“组”的答复,为什么不定义一个可扩展的回复标题,不仅包括地址而且包括回复的类别? 就像是:

标签回覆:秘书; jeeves@cs.utk.edu标签回复:邮件列表; listname@foo.com

事实证明,我们已经在RFC 822中有大部分:

  • 地址之前的“短语”或评论可以通过名称和/或角色识别人。 回复者可以使用这些信息来决定是否合理地向该人发送回复。 例如

      Reply-To: (my secretary) <EM>jeeves@cs.utk.edu</EM>
  • 类似地,组名之后的“短语”可以标识一组接收者,也可以由响应者使用。 例如

      Reply-To: Secretary: jeeves@cs.utk.edu ;,
The Gang: a@foo, b@bar, c@zot ;

(不幸的是,短语被广泛地困扰,他们可能不能用于此。)

概要:

  • 解决大多数答复问题的方法是鼓励回应者真正考虑消息需要去哪里,并使他轻松获得他想要的行为。 (如果人们使用RFC 822“短语”来标记他们的标题地址,它也有帮助。)
  • 我们可以构建接口,帮助响应者执行此操作,而无需定义任何新的头域。
  • 除了极少数情况之外,Mail- {Reply,Followup} -To没有帮助。 它只提供更多的令人惊讶的行为的机会。

不锈钢大鼠ratinox@peorth.gweep.net 1998-02-12在Emacs丁邮件列表中发表评论

每个邮件客户端都不支持这一点。 只有严重的书面材料才能区分答复和跟进。

当你直接了解这个建议的标准有两个目标:

  1. 使破碎的MUAs不那么破碎。 那么,破坏的MUAs不会执行这个标准,反正; 良好的MUAs不需要它,因为它们已经使回复和跟进之间区分开来。
  2. 使破碎的邮件列表的行为不那么简单。 破损的邮件列表的管理员已经决定他们喜欢这样。 他们声称,它使列表的用户更容易回复列表。 “需要”列表回复标题的订阅者正在使用破坏的MUA。 见#1。

    这个提出的标准不会解决它试图解决的任何问题。 它创建了被不良MUAs忽略的头,并且对于良好的MUA而言是冗余的。

    总结Keith的声明:From是发起人的邮箱。 它不是一个“帐户”。 RFC 822规定发起者头部应包含正确的默认回复地址。

    这是这些头文件提出者提出的方案,也是IETF发现的缺陷。

    乔订阅了他从他的“私人”邮件帐户中读取的邮件列表。 无论什么原因,Joe从工作中向该列表发布了一条消息,因此他的工作邮箱位于From头。 Joe不想用回覆标题来覆盖响应的位置,但他希望个人回复可以转到他的私人邮箱帐户,而不是他的工作账户。

    IETF发现的缺陷是Joe将他的两个邮箱与他的私人和工作帐户相等。 就RFC 822而言,没有这样的对应关系。 如果乔以“私人”的方式行事,他所使用的制度是无关紧要的; 他的私人邮箱属于From头,当他发送邮件时,应该将该邮箱放在那里,而不管他的身体状况如何。

    23.10 Mail-Copies-To标题

    [由阿尔卡斯Gnus的作者拉尔斯建议]

    ... Mail-Copies-To:是Usenet上的消息中使用的标题行,通过后续邮件的邮件将副本指向帖子。 http://www.newsreaders.com/misc/mail-copies-to.html

    [SL Baur steve@xemacs.org ] Mail-Copies-To:头应该控制您的邮件(和Usenet)客户端如何准备后续消息。 它可以向消息的发送者控制是否应该发送消息的重复副本。 有两种形式:

          Mail-Copies-To: never

    不要自动包含正在回复的邮件的发件人。 有两个规范的例子。

          Usenet:
    From: foo@foo.bar
    Newsgroups: comp.emacs.xemacs
    Mail-Copies-To: never

    符合客户端的跟进应在响应消息头中生成:

          Newsgroups: comp.emacs.xemacs

    Email:
    From: foo@foo.bar
    To: mailing-list@somewhere.com
    Cc: luser@somewhereelse.com
    Mail-Copies-To: never


    符合客户端的跟进应在响应消息头中生成:

          To: mailing-list@somewhere.com
    Cc: luser@somewhereelse.com

    第二种形式包括一个正确形成的RFC822邮件地址作为参数:

          Mail-Copies-To: someaddress@somewhere.com

    在这种情况下,邮件的发件人特别要求对邮件的回复不仅可以转到主要论坛(邮件列表或Usenet新闻组),而且复制副本也应发送到someaddress@somewhere.com 。 有(再)两个规范的例子。

          Usenet:
    From: foo@foo.bar
    Newsgroups: comp.emacs.xemacs
    Mail-Copies-To: foo@foo.bar

    符合客户端的跟进应在响应消息头中生成:

          Newsgroups: comp.emacs.xemacs
    Cc: foo@foo.bar[1]

    Email:
    From: foo@foo.bar
    To: mailing-list@somewhere.com
    Cc: luser@somewhereelse.com
    Mail-Copies-To: foo@foo.bar

    符合客户端的跟进应在响应消息头中生成:

          To: mailing-list@somewhere.com
    Cc: luser@somewhereelse.com, foo@foo.bar[2]

    邮件复制中的地址与发件人地址不匹配。 脚注:[1]或`To:foo@foo.bar'[2]也可以将foo@foo.bar放在To:行中。

    23.11邮件跟随和回复个人标题

    [1997年11月21日,马特发展清单<mutt-dev@cs.hmc.edu]

    雅各布·帕尔姆(Jacob Palme)刚刚提交了一篇描述邮件跟进的互联网草案。 雅各布,工作组主席克里斯·纽曼和我都认为这是对我自己的“回复个人”提案的补充,这是我在这里发布的早期版本,也是今天提交的一个互联网草案。 事实上,我周末已经有点少了雅各布,我会发出一个联合草案。 在几天之内,您应该可以在ds.internic.net的IETF草案目录中查看这些草案,名称

    draft-ietf-drums-mail-followup-to-00.txt Jacob Palme的草案提出了Mail-Followup-To标题。

    draft-ietf-drums-replyto-personal-00.txt我的个人回复的草稿

    23.12 Content-Length头和From_规范

    [1996-05-17 From:Jamie Zawinski jwz@netscape.com comp.mail.headers]

    ...我不是说BSD邮箱格式不错。 只是该格式的Content-Length变体更糟。

    好的,所以有人采用From_格式,并且通过在格式中添加长度指示器来扩展它,不需要改变。 乍看起来,这听起来可以简单而优雅,但它打破了世界,不应该鼓励它的传播。

    破坏的事情是采取现有的,广泛实施的格式,并增加一个要求,它有一个长度指示器。 这意味着任何已经认为知道如何操纵该格式的现有软件会损坏文件(数据的任何更改将导致长度指示符对于新规范而言是错误的,但不符合旧规范。)

    如果基于内容长度的格式不是与“从”格式不可区分,则不会有问题; 旧的软件将无法使用这种新的文件格式,而不是“破坏 ”这些文档(引号,因为它只是一个关于你所遵循的规范的问题)。

    另外邮箱本质上是一种文本格式; 但是,内容长度头部以字节为单位而不是行。 这意味着如果将文件移动到具有不同行尾表示的系统(Windows <=> Mac或Windows <=> Unix),那么内容长度将突然出错,因为现在线路断开两个字节而不是一个,反之亦然。

    邮件客户端不可能查看文件,并且说明它所在的两种格式(From_或Content-Length)中的哪一种; 它们在程序上是无法区分的。 一个Content-Length头部的存在是不够的,因为假设你在一个什么都不知道该标题的系统上,而一些传入的消息恰好恰好在它的头部。 那么那个标题最终会在您的邮箱中(因为没有人知道删除或重新计算它),它可能是不正确的。 (进一步假设标题不只是错误,而是故意恶意...)

    “从”分隔符线更严格的解析也没有帮助,因为在该行中有很多变化很多(因为它从不标准化); 而且,一些邮件阅读器在转发消息时(例如Sun的MailTool)会逐字地包含该行,因此,更严格的解析器根本不会帮助这种情况,因为消息体往往包含有效的匹配。

    一些邮件阅读器尝试通过识别Content-Length不明显是目标位置的情况,然后向前和向后搜索最近的消息分隔符来尝试应对这种情况。 但这显然不是万无一失的,而且使解析器效率更低(需要任意的前瞻和回溯)。

    传统的智慧是,“如果你相信Content-Length标题,我有一座桥卖给你”。

    23.13关于新西兰的CC副本的道德

    发送CC

    在gnu.emacs.gnus(例如1999-03-20左右)新闻组中,有很多人热烈讨论,许多人认为将CC答复发送给新闻组。 发送CC的好处被看作是:

    • 该人得到快速答复。
    • 该人不定期阅读新闻组,并欣赏私人回答
    • 他的新进给可能不是很可靠,所以答案可能不会出现在组中(但我们不知道这一点)
    • 新团体到期时间可能太快了,无法捕捉回覆(但我们不知道这一点)。

    近年来netnews发生了很大变化,很多人开始使用不存在的邮箱地址,以防止发送UBE邮件。 这使得“CC”发件人感到懊恼,因为他们从这些不存在的地址中收到邮件。

    不发送CC

    Usenet被认为是一个公共论坛,它不强迫任何人不想透露他们的“真实”地址。 和门锁一样。 有些人不想看到非邀请的人在门口,这就是为什么他们不喜欢CC消息:

    • CC是多余的:答案已经发布到新闻组
    • CC不会帮助跟随线程。 人们必须访问新闻组才能看到整个讨论。
    • CC受到邮件发送问题:人已移动,邮件发送问题(持续N天),暂时失败..
    • 他总是想阅读新闻组,不喜欢CC副本在昂贵的ISP帐户中填写他的邮箱。

    一个清晰的地址

    一个明确的不存在的邮件地址,表示它不是真正的目的地通常被认为是很好的礼仪:

          john.doe@nowhere.net
    b.gates@vatikan
    dummy@no-replies.com

    或部分修改,如果需要直接联系(但对程序有些困难,因为有更多创造性的选择,程序可以期望看到),人类的心灵可以“解码”:

          johnx.you-know-what-todo@not-here.skynet.com
    door.lock.mike@chevanix.com
    nospam.xavier@ube-stop.aol.net

    一个有效的地址

    但是,一个看起来像一个“真实”但是虚伪的地址并不是一个有礼貌的方式来参与Usenet。 这个地址给人的印象是,persn真的在那里:

          mike@future-domain.com

    关于自动CC副本的MORAL了解到:

    自动CC是一件坏事。 不要猜想人们的想法。 一封公开的邮件(真实邮件地址)不是邀请他访问他的门。 这只是一个提示信息来自(有效或不有))。 我们唯一可以确定的是,一个明确的反UBE地址是一个停止的标志,不发送任何CC副本。

    当人们想要CC时,他们通过邮件来表示它,或者添加一些可以被邮件阅读者理解的标题,例如邮件拷贝到跟踪。

该文件已使用Perl脚本t2html.pl v2004.0428的纯文本文件自动生成
最后更新:2004-10-06 16:57


本文档的原始位置: http : //pm-doc.sourceforge.net/pm-tips.html

赞(52) 打赏
未经允许不得转载:优客志 » 系统运维
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏