*** 00READ_ME.WIDE.ORG Wed Aug 1 16:28:43 2007 --- 00READ_ME.WIDE Wed Aug 1 18:15:27 2007 *************** *** 0 **** --- 1,192 ---- + Patch kit for R8 sendmail (3.5W) by WIDE Project + Aug.1,2007 + Motonori NAKAMURA + WIDE Project + motonori@wide.ad.jp + + INTRODUCTION + + This patch-kit provides some enhancement for the sendmail. Please apply + this patch if you want to use "smtpfeed", which is an external SMTP mailer. + + Current original sendmail includes many features, especially for Japanese + workstations, which had been offered with patch kit 2.xW by WIDE Project. + Many normal workstations (non-mail-servers), therefore, will not need + features offered by this patch-kit. Be sure on features offered by + this patch-kit if you apply it to the sendmail. + + + FEATURES + + Each features are enabled/disabled with the following flags in conf.h. + + QUICK_RESPONSE + When sendmail is executed with -odq switch from rmail program, + bounce mails will also be queued. If feature is enabled, bounce + mails will not be queued and sent immediately (not well tested). + + MULTI_MAILER + This feature allows multiple description of the triple in a rule + for mailer dispatching in ruleset 0 or its sub-rulesets like: + R$*<@dom>$* $#smtp$@dom$:$1<@dom>$2 $#uucp$@dom$:$1<@dom>$2 + The above rule will try smtp mailer at first and then try uucp + mailer if smtp mailer fails. + Lower number limit of recipients can be defined at *= equate + in definition line of a mailer which will be used at first. + If number of recipients is less than the value defined at *= + equate, first mailer will be skipped without trial. + Message size limitation defined by M= equate will also be treated + like the above -- if size of message is larger than the value + defined, first mailer will be skipped without trial. + If there is a flag '!' in F= equate, the mailer will be skipped + when queue processing (in case following mailer is found). + If there is a flag '_' in F= equate, the following mailer will + not be used when the mailer (having '_' flag) is tried and + failed with TEMPFAIL response code. + + CF_ALIASING + This feature supplies "aliasing" in ruleset 5 (ruleset 5 is + applied after aliases expansuin). + The following rule will forward messages for user-a to multiple + recipients, user-a and user-b. In other words, this feature + provides aliasing by rules of the sendmail.cf. + R user-a $# local $@ alias $: user-a, user-b + A mailer specified at $# must have 'l' in F= equate (local mailer). + host portion specified at $@ must be 'alias'. + You can specify multiple addresses separated with ',' at $: + + MAILER_PREF + Mailer preference can be defined in configuration file to determine + order of mailers to be executed. If a message which has multiple + recipients will be delivered with multiple mailers, order of mailers + is determined by preference values. For example, if you define 10 + for local mailer and 20 for smtp mailer, delivery with local mailer + will be done first and then smtp mailer will be used. Preference + values can be defined at %= equate on mailer definition lines. + Lower values are more preferred like MX RRs. Default value is 0 + in case %= equate is missing. Negative values can be specified. + If there is a flag '<' in F= equate of a mailer definition, + list of destination addresses for the mailer will be sorted by + domain part. This feature will be effective if number of recipients + to be processed in one transaction is limited with r= equate. + + CLIENT_SMTP_CONFIG + 3 parameters of client-side SMTP connection can be configured. + Parameters are: + FQDN: FQDN used as a hostname with SMTP HELO + SrcIPaddr: source IP address for client-side SMTP (12.34.56.78) + SrcPort: source port number for client-side SMTP + Define these parameters at @= equate on IPC mailer definition lines + like: + @=FQDN/SrcIPaddr/SrcPort + Default value will be used if a parameter omitted. + When a '@' is specified at FQDN part, a hostname which is resolved + from source IP address of SMTP connection dynamically is used. + If any hostname can not be obtained with DNS or etc., [IP.addres] + notation will be used. + When a '@' is specified at SrcIPaddr part, an IP address associated + with FQDN will be used. If multiple IP addresses are defined for the + FQDN, the first found address will be used. + + CTE8CHECK + Manage incorrect "Content-Transfer-Encoding: 8bit" header label + (having such a header without 8bit data in message body). + To enable this feature, CTE8BitCheck option should be defined in + configuration file. + O CTE8BitCheck=correct (correct CTE label to "7bit") + O CTE8BitCheck=reject (reject such messages) + + OO_NULLSENDER + Set NULL sender envelope address (<>) on messages delivered to + the alias entry "owner-owner" to avoid loops. + + MF_SEPARATE + Even if recipient list of a message includes multiple identical + address, only one copy of the message will be sent to the address. + If you define MF_SEPARATE and set flag '^' to a mailer, the + address will not be unified and equal number of copies will be + sent to the address. + + MASKED_ADDR + Traditional class-macro matching in sendmail is just a tokenized + character string pattern matching. But this type of matching does + not support masked IP address matching, so you must list up every + host addresses as elements of a class. It is complicated especially + for IP address authentication in check_* rulesets. + If you define MASKED_ADDR, masked IP address matching feature can + be used. For example, if you describe the following lines in your + sendmail.cf, an IP address between 172.16.0.0 and 172.31.255.255 + will be matched to $=C in a rule. + + CC _MASKED_ADDRESS_MATCH_ + CC 172.16.0.0/12 + + Note that you must include the keyword _MASKED_ADDRESS_MATCH_ to + a class to enable masked IP address matching for the class. + + If you define MASKED_ADDR, maskedaddr map is also enabled. + For example, if you create a map file /etc/maskedaddr.map with + the following content: + + 172.16.0.0/12 OK + + and describe the following lines in your sendmail.cf, an IP + address between 172.16.0.0 and 172.31.255.255 will match to + the entry in the map file, and the address pattern will be + changed to "OK". + + Kma maskedaddr -t /etc/maskedaddr.map + + R $-.$-.$-.$- $: $( ma $1.$2.$3.$4 $) + + This map file is not DB style but TEXT style, so the file will + be open and read at every matching processing. If you set option + -t as avobe example, the file will be read only once at startup + time of sendmail. In this case, you must restart sendmail when + you modified the map file. + + 3ffe:501::1 address spec is also supported under IPv6 environment. + + SPR_CON_CACHE + This feature supplies connection-caching control par mailer basis. + You can use mailer flag ';' at F= equate of mailer definition. + If your set the mailer flag ';', connection-caching feature for + the mailer is disabled. + + FORWARDPROGCTL + This feature supplies privilege control on execution of programs + via ~/.forward file. With this feature, only users defined in + class macro 'f' can execute programs via ~/.forward. To enable + this feature you must also define a character '@' in the class + macro 'f', or every users can execute programs via ~/.forward. + + MAILER_TIMEOUTS + With this feature, you can control message timeout (how long + an unsent message will be kept in the mqueue) par mailer basis. + To specify timeout value for a mailer, use ?= equate like: + Msmtp ...., ?=7d,.... + + CHECK_WARNING + This enables a feature to control whether a queue-warning + (unsent yet, but still trying) notification should be sent to + sender or not. For decision, envelope sender address is processed + with "check_warning" ruleset and if it reaches to an error mailer, + a notification will be sent. Of course, notifications to messages + whose value in Precedence: header field is negative or envelope + sender address is <> are not sent as before. If "check_warning" + ruleset is not defined, notifications are sent as before. + An example of check_warning ruleset: + Scheck_warning + R $* - request@$* $@ OK + R $* - ctl@$* $@ OK + R owner - $*@$* $@ OK + R $* @ mydomain $#error$:warning + R $* $@ OK + Note: in check_warning ruleset, character '-' is also treated as + an OperaterChar. But it should be surrounded by spaces. + + + ACKNOWLEDGEMENTS + + Development of this patch-kit has been supported by WIDE Project, Kyoto + University, Ritsumeikan University, TDI Co., Ltd., and many contributors. *** 00READ_ME.WIDE.j.ORG Wed Aug 1 16:28:43 2007 --- 00READ_ME.WIDE.j Wed Aug 1 18:16:09 2007 *************** *** 0 **** --- 1,217 ---- + Patch kit for R8 sendmail (3.5W) by WIDE Project Aug.1,2007 + 中村 素典/WIDE Project + motonori@wide.ad.jp + + 《はじめに》 + + このパッチキットは、sendmail に対して SMTP による配信を行う外部メーラで + ある smtpfeed を利用するための変更を中心とした拡張を行なうためのものです。 + + 現在のオリジナルの sendmail には、従来の WIDE 版 sendmail として提供され + てきた多くの機能が取り込まれているので、ほとんどの場合はオリジナルのまま + で問題なく利用できます。特に、日本製のワークステーションでうまくコンパイ + ルできない、という問題はほとんど解消されていますから、これをあてればコン + パイルできるようになるというパッチではありません。このパッチによって実現 + される機能の必要性を十分に検討してからご利用下さい。 + + + 《拡張される機能について》 + + 各種機能は以下のフラグによって制御できます。 + + QUICK_RESPONSE + rmail などから -odq フラグつきで sendmail が起動された場合、配信 + エラーが発生しても、エラーメールは mqueue に一旦保存されます。この + ようなレスポンスメールについては、mqueue に落さずにすぐに配送する + ようにしたい場合に 1 にします(テストが十分でないので注意)。 + + MULTI_MAILER + ルールセット 0 のメーラディスパッチルールにおいて、一行に + $#...$@...$:... の三つ組を繰り返し記述できるようにします。 + $#smtp.... $#uucp.... のように書くことにより、smtp mailer による + 配送に失敗した場合に、即座に uucp mailer に切替えて配信させるよう + にすることができます。 + sendmail.cf の mailer 定義行において *= 式が指定された場合、受信者 + 数がその式に指定された数値に満たない場合で、さらに後続の mailer が + 存在する場合には、当該 mailer は利用せずに後続の mailer に skip し + ます。 + また、M= 式で指定されるメッセージサイズについても、上限を越えてお + り、かつ後続の mailer が存在する場合には、同様に skip します。 + F= 式に mailer flag ! を追加した場合、run queue の際には利用されず + に、後続の mailer に skip します(後続の mailer が定義されている場合 + のみ)。 + F= 式に mailer flag _ を指定した場合、この mailer が起動されたなら + ば、先行する mailer の処理結果が TEMPFAIL になっても後続の mailer + を試みません。 + + CF_ALIASING + ルールセット 5 のローカルユーザに関する書き換えルールにおいて、エイ + リアス機能(複数のアドレスに展開する機能)を提供します。つまり、 + CF_ALIASING は aliases の機能を、sendmail.cf のルールレベルで提供し + ます。例えば、S5 で始まるルールセット5に以下のようなルールを書くこ + とで、user-a 宛のメールは user-a および user-b に送られるようになり + ます(ルールセット 5 は aliases の処理の後で適用されます)。 + R user-a $# local $@ alias $: user-a, user-b + $# で指定する mailer は F= に l を持つローカルメーラです。 + $@ では必ず alias を指定します。 + $: で、aliases ファイルのように、複数のアドレスをコンマで区切って + 指定します。 + + MAILER_PREF + mailer の起動順序の設定を可能にします。複数の宛先を持つメッセージが + 複数の mailer を利用して配信される場合、mailer ごとにあらかじめ指定 + された順位付けに従って、配信が行なわれます。例えば、local mailer に + 対して 10、smtp mailer に対して 20 という値を設定しておくと、まず + local mailer を経由する配信処理を済ませてから、smtp mailer を経由 + する配信処理に移ります。順位付けのための値は、mailer 定義行の %= 式 + で指定します。より小さな値を持つ mailer の処理が優先されます。 + %= 式を定義しなかった場合のデフォルト値は 0 です。負の数も指定可能 + です。 + また、F= 式に mailer flag < が指定された mailer については、配送先の + アドレスがソートされてから処理されます。 r= 式で一回の処理で渡される + アドレス数が制限される場合に、できるだけ同じアドレスを同時に処理させ + たい場合に有効でしょう。 + 従来のパッチで提供されていた LOCAL_FIRST は、この機能に置き換えられ + ました。 + + CLIENT_SMTP_CONFIG + SMTP によってメールを配信する際の、発信側サイドに関するいくつかの + 設定を可能にします。ここで可能になるのは、SMTP の HELO コマンドで + 名乗るホスト名、ソース IP アドレス、ソースポート番号です。 + 設定は mailer 定義行の @= 式にて行ないます。 + 形式は @=family:FQDN/SrcIPaddr/SrcPort で、各項目は以下の通りです。 + family: inet または inet6 + FQDN: SMTP HELO で使用されるホスト名 + SrcIPaddr: ソース IP アドレス(12.34.56.78 という形式で記述) + SrcPort: ソースポート番号 + / で区切られた項目のいずれかを省略した場合は従来のデフォルト値が + 使用されます。 + FQDN に @ のみを指定した場合は、SMTP 接続で用いられているソース側 + IP アドレスに対応づけられている名前を動的に検索し、それを用います。 + もし、DNS 等に対応するホスト名が登録されていなかった場合は、 + [IP.addres] 表記を用います。 + SrcIPaddr に @ のみを指定した場合は、FQDN に対応する IP アドレスが + 利用されます。FQDN に複数の IP アドレスが対応づけられている場合は、 + 最初に見つけたアドレスを使用します。 + + CTE8CHECK + 本文が 8bit 文字を含まないメッセージであるにもかかわらず、 + Content-Transfer-Encoding: に 8bit を指定して送信されてくるメッセー + ジをチェックし、オプションで指定した処理を行ないます。オプション名 + は CTE8BitCheck です。 + O CTE8BitCheck=correct + CTE: に記述された 8bit を強制的に 7bit に変更します。 + O CTE8BitCheck=reject + 配信を拒否します。 + + OO_NULLSENDER + owner-owner というエイリアスエントリにメールが送信された場合に、 + エンベロープの発信者アドレスを NULL アドレス (<>) に書き換えます。 + これは、配信先におけるエラーのためのループを避けるためです。 + + MF_SEPARATE + 通常、メールの配信時に同一の宛先が複数含まれている場合には、その + 宛先には一通しかメールが送られませんが、MF_SEPARATE を定義すると、 + そのような場合であっても複数のメールが送られるようにするための機 + 能が利用可能になります。MF_SEPARATE を定義すると、mailer flag ^ + が利用可能になるので、メールを一つにまとめたくない mailer の flag + に ^ を追加してください。 + + MASKED_ADDR + 通常、sendmail における文字列マッチングは、単純なパターンマッチン + グによって処理されます。しかし、このような文字列マッチングでは、 + ネットマスクを伴う IP アドレスの範囲マッチングができず、IP アドレ + スによる認証処理などの記述が非常に煩雑になってしまいます。 + MASKED_ADDR を定義すると、sendmail.cf のクラスマッチングにおいて + ネットマスク表記を含んだクラス要素へのマッチング機能が利用可能に + なります。例えば、 + + CC _MASKED_ADDRESS_MATCH_ + CC 172.16.0.0/12 + + と定義しておくと、172.16.0.0 から 172.31.255.255 までのアドレスは + ルール中の $=C にマッチします。なお、このマッチング処理を利用した + いクラスに対しては、その要素として _MASKED_ADDRESS_MATCH_ を定義 + しておく必要があります。_MASKED_ADDRESS_MATCH_ を要素に持たないク + ラスは、従来通りのマッチング処理を行います。 + + また、MASKED_ADDR を定義すると、maskedaddr マップが利用可能になり + ます。例えば、次のような内容のマップファイル /etc/maskedaddr.map + を用意しておき、 + + 172.16.0.0/12 OK + + sendmail.cf で次のように定義すると + + Kma maskedaddr -t /etc/maskedaddr.map + + R $-.$-.$-.$- $: $( ma $1.$2.$3.$4 $) + + 172.16.0.0 から 172.31.255.255 までのアドレスに対して、マップファ + イル中のエントリがマッチし、OK に書き換えられます。このマップファ + イルはテキスト形式で、データベース形式への変換は必要ありません。 + そのため、マップファイルをマッチング処理の度に毎回読み込むことに + なります。起動時に一度だけ読み込むようにしたい場合は、上の例のよう + に -t オプションを指定します(この場合、マップの変更後は sendmail + の再起動が必要です)。-t オプションを指定しない場合は、毎回マップ + ファイルが読み込まれます。 + + なお、IPv6 環境では 3ffe:501::1 といった表記にも対応します。 + + SPR_CON_CACHE + メーラ単位にコネクションキャッシュ機能を抑制する機能を提供します。 + メーラフラグ ; をメーラ定義(M行)の F= に追加することで、そのメー + ラの処理に関してコネクションキャッシュ機能が抑制されます。 + + FORWARDPROGCTL + .forward においてプログラムを実行できる権限を特定のユーザのみに制 + 限する機能を提供します。この機能が有効になっている場合、クラス f + に登録されているユーザのみが、プログラムの実行を許されます。この + 機能を有効にするには、クラス f に文字 @ を登録しておきます。クラ + ス f に文字 @ が登録されていなければ、通常通り誰でもプログラムを + 実行することができます。 + + MAILER_TIMEOUTS + 配信未完了状態が続いているメールはキューに保存されますが、ある期 + 限を過ぎると、発信者に返送されます。この期限を、メーラ毎に指定で + きる機能を提供します。sendmail.cf のメーラ定義行(Mで始まる行)に + おいて ?= 式で、そのメーラでの保存期限を指定します。 + 例: + Msmtp ...., ?=7d,.... + + CHECK_WARNING + 配信未完了状態が続いた場合、sendmail は発信者に「未完了であるが、 + 継続して試行する」という旨を通知する機能を持っています。この期限 + は Timeout.queuewarn などで設定しますが、標準では、全ての通常メー + ルに関して通知を出すか出さないかの選択しかできません。 + CHECK_WARNING は、この通知を選択的に行うようにするための機能を提 + 供します。新たに check_warning ルールセットが用意され、このルール + セットに対して、エンベロープの発信者アドレスが渡されます。このルー + ルセットが定義されている場合、処理の結果が error mailer を含むも + のであった場合は通知が発信され、そうでない場合は通知の発信は抑制 + されます。check_warning ルールセットが未定義の場合は、通常通りの + 動作となります(check_warning が定義されていても、これまで通り、 + Precedence: ヘッダの値が負であるものや、エンベロープの発信者アド + レスが <> であるものに対する通知は抑制されます)。 + check_warning ルールセットの例: + Scheck_warning + R $* - request@$* $@ OK + R $* - ctl@$* $@ OK + R owner - $*@$* $@ OK + R $* @ mydomain $#error$:warning + R $* $@ OK + なお、check_warning ルールセットでは、文字 '-' も、OperatorChars + として扱われます。ルールセットを記述する場合は、上記のように、 + 文字 '-' の前後にはスペースをいれるようにします。 + + RCPT_HASH + 一度に多数のアドレスを扱う場合(大規模なメーリングリスト等で)、 + 同一アドレスの存在の有無をチェックする処理がリニアサーチになっ + ているため処理が遅い。RCPT_HASH は、ハッシュを用いてこの処理を + 高速化する。十分な動作確認が行われていないので注意。 + + 《謝辞》 + + このパッチは、WIDE Project、京都大学、立命館大学、情報技術開発株式会社 + ならびにその他の人々の協力によって作成されたものです。ここに感謝の意を + 表します。 *** COPYRIGHT.WIDE.ORG Wed Aug 1 16:28:43 2007 --- COPYRIGHT.WIDE Wed Aug 1 16:28:43 2007 *************** *** 0 **** --- 1,30 ---- + * Copyright (c) 1995-2002 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by WIDE Project and + * its contributors. + * 4. Neither the name of the Project, the University nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. *** INSTALL.WIDE.ORG Wed Aug 1 16:28:43 2007 --- INSTALL.WIDE Wed Aug 1 18:17:54 2007 *************** *** 0 **** --- 1,23 ---- + INSTALLATION + + This kit is provided in a "patch" format. Simply apply it in the directory + sendmail-8.14.1/sendmail/. + + 1. gunzip sendmail.8.14.1.tar.gz + 2. tar xvf sendmail.8.14.1.tar + 3. cd sendmail-8.14.1/ + 4. patch < THISFILE + + If your system does not have the "patch" program. Install the GNU version + of "patch." + + After applying the patch, type "sh Build" to make binary of sendmail. + + 5. sh Build + + and install new sendmail carefully ("make install" does not save + old binaries to revert). + + Read 00READ_ME.WIDE to utilize features provided by this patch-kit. + You should, of course, read other documents such as READ_ME or FAQs + included in the original distribution of the sendmail. *** INSTALL.WIDE.j.ORG Wed Aug 1 16:28:43 2007 --- INSTALL.WIDE.j Wed Aug 1 18:17:42 2007 *************** *** 0 **** --- 1,16 ---- + 《インストール方法》 + + このパッチキットは、パッチ形式による配布となっています。sendmail.8.14.1.tar + を展開してできたディレクトリ sendmail-8.14.1/ の中で + patch < "パッチファイル名" + として当てください。patch コマンドは GNU のものを利用することを推奨します。 + + パッチを当てた後、オリジナルの sendmail のコンパイルと同様に sh Build を + 実行します。Build は、BIND8 や NEWDB の環境の存在も自動チェックします。 + include や lib のディレクトリを追加するには、Build の -I や -L オプション + で適宜補ってください。 + + その他、sendmail 8.14.1 の利用にあたっては、オリジナルの sendmail に付属 + の READ_ME や FAQ 等も良く読んでください。また、このパッチの機能を効果的 + に利用するための sendmail.cf の設定については、00READ_ME.WIDE ファイルを + 参照してください。 *** RELEASE_NOTES.WIDE.ORG Wed Aug 1 16:28:43 2007 --- RELEASE_NOTES.WIDE Wed Aug 1 18:18:51 2007 *************** *** 0 **** --- 1,308 ---- + Sep. 1, 2007/8.14.1+3.5Wbeta + applied to 8.14.1 + + Apr. 19, 2002/8.12.3+3.5Wbeta + applied to 8.12.3 + PATCHFILE: + working directory to execute "patch < PATCHFILE" is changed + from sendmail-8.xx.xx/sendmail/ to sendmail-8.xx.xx/. + collect.c: + _MICROSOFT_TIMEZONE_HACK_ removed + deliver.c: + DYNAMIC_TOBUF is supported by 8.12 + + Aug. 25, 2001/8.11.6+3.4W + applied to 8.11.6 + + Aug. 15, 2001/8.11.5+3.4W + applied to 8.11.5 + + Jun. 4, 2001/8.11.4+3.4W + applied to 8.11.4 + + Mar. 4, 2001/8.11.3+3.4W + applied to 8.11.3 + ${runqueue} is no longer defined. use ${ntries} instead. + + Jan. 21, 2001/8.11.2+3.4W + applied to 8.11.2 + + Nov. 16, 2000/8.11.1+3.4W + applied to 8.11.1 + + Aug. 18, 2000/8.11.0+3.4W + recipient.c: + same addresses were not unified. + remove spaces before #@# sequence (start of comment). + + Jul. 30, 2000/8.11.0+3.3W + applied to 8.11.0 + DYNAMIC_TOBUF is implemented in original sendmail, + but for future release. + !!! CAUTION !!! equate character %= changed to r=. + + Jun. 12, 2000/8.10.2+3.3W + applied to 8.10.2 + + Apr. 15, 2000/8.10.1+3.3W + applied to 8.10.1 + LOGWVERSION deleted. + BOUNCE_REASON deleted. (officially supported by 8.10) + DEFINE_MAP deleted. (officially supported by 8.10) + !!! CAUTION !!! mapname changed from "define" to "macro". + mailer flag characters are changed on MULTI_MAILER feature: + '-' is replaced by '_'. + mailer flag characters are changed on MAILER_PREF feature: + '%' is replaced by '<'. + mailer flag characters are changed on MF_SEPARATE feature: + '+' is replaced by '^'. + + Mar. 6, 1999/8.9.3+3.2W + parseaddr.c: + !!! CAUTION !!! CF_ALIASING feature modified. + You can use aliasing in ruleset 5 as follows: + R user@domain $#local$@alias$: alias1,alias2,... + Mailer must be a local mailer (F= includes 'l') and host + part must be "alias". + conf.h, sendmail.h, recipient.c: + FORWARDPROGCTL added. + If you define a character '@' in the class macro 'f', + only users defined in the class macro 'f' can use + 'prog' mailer via his/her ~/.forward. + conf.h, sendmail.h, readcf.c, savemail.c, envelope.c: + MAILER_TIMEOUTS added. + Queue-return timeout par mailer can be defined with ?= equate + like: Msmtp ...., ?=7d,.... + conf.h, envelope.c: + CHECK_WARNING added. + Queue-warning timeout operation can be controlled with the + check_warning ruleset. Envelope sender address will be + processed with the check_warning ruleset. If the chech_warning + ruleset is defined and the sender address does not reach to + an error mailer, queue-warning message will be suppressed. + e.g.: + Scheck_warning + R $* - request@$* $@ OK + R $* - ctl@$* $@ OK + R owner - $*@$* $@ OK + R $* @ mydomain $#error$:warning + R $* $@ OK + readcf.c: + O_CTE8CHECK should not be 0xaa (fix). + sendmail.h, deliver.c: + mailer flag ';' added to suppress connection caching -- to + change process of external mailer. + deliver.c: + use strcpy() instead of strcat() for performance improvement + daemon.c: + initialize a pointer "hp" to NULL + reported by Kojima Kenichi + recipient.c conf.h sendmail.h: + RCPT_HASH feature added + + Feb. 19, 1999/8.9.3+3.1W + applied to 8.9.3 + deliver.c: + enable SuperSafe on LMTP data response + map.c: + fix return value in maskedaddr_build() + reported by Toshiki Ohkawa + conf.c: + still use _PATH_SENDMAILCF in case of NETINET6 + + Jan. 13, 1999/8.9.2+3.1W + applied to 8.9.2 + + Sep. 24, 1998/8.9.1+3.1W + queue.c + ${runqueue} defined if in runqueue processing + main.c + //coment to be echoed in test mode + map.c, parseaddr.c, conf.c: + masked address matching support by class macro (MASKED_ADDR) + many files: + IPv6 support + map.c, conf.c: + macro can be defined dynamically in a rule with map (DEFINE_MAP) + + July 3, 1998/8.9.1+3.0W + applied to 8.9.1 + + May 26, 1998/8.9.0+3.0W + parseaddr.c + alias expansion supported in ruleset 5 (CF_ALIASING) + the following rule in ruleset 5 splits an envelope for + a recipient (user) into 2 recipients (user1 and user2). + R user $# local $: user1 $# local $# user2 + + Apr. 30, 1998/8.9.0+3.0Wbeta14 + domain.c + CANON_OTHER feature removed. + deliver.c + mailer flag % added to sort address list + + Mar. 17, 1998/8.9.0+3.0Wbeta13 + applied to 8.9.0 + + Mar. 6, 1998/8.8.8+3.0Wbeta13 + deliver.c + more fix around smtpquit() (mci pointer was not initialized) + + Mar. 5, 1998/8.8.8+3.0Wbeta12 + deliver.c + fix around smtpquit() + + Jan. 6, 1998/8.8.8+3.0Wbeta11 + readcf.c + =M support in test mode (values defined with %=, @=, *=, &=, + etc. are shown), + deliver.c + show preference values (defined with %= equate) in -bv mode. + + Jan. 5, 1998/8.8.8+3.0Wbeta10 + deliver.c, readcf.c: + Fix on MAILER_PREF. + Implementation in beta9 has not any effect. + + Jan. 4, 1998/8.8.8+3.0Wbeta9 + !!! CAUTION !!! MaxSendRcptPerMessage option is obsolete. + Use &= equate at mailer definition instead. + new features: + MAILER_PREF + Mailer preference can be defined in configuration file + to determin order to execute. Define numerical values + at %= equate on mailer definition lines. Lower values + are more prefered like MX RRs. + CLIENT_SMTP_CONFIG + To configure parameters of client-side SMTP connection. + Define three parameters at @= equate on IPC mailer definition + lines: @=FQDN/SrcIPaddr/SrcPort + FQDN: FQDN used as a hostname with SMTP HELO + SrcIPaddr: source IP address for client-side SMTP + SrcPort: source port number for client-side SMTP + Default value will be used if a parameter omitted. + CTE8CHECK + Manage incorrect CTE: 8bit header label (without 8bit data + in message body). To enable this feature, CTE8BitCheck + option should be defined in configuration file. + O CTE8BitCheck=correct correct CTE to 7bit + O CTE8BitCheck=reject reject such messages + BOUNCE_REASON + Show reason on each address reported in bounceed message. + OO_NULLSENDER + Set NULL sender address (<>) on messages delivered to + the alias entry, owner-owner. + + Dec. 25, 1997/8.8.8+3.0Wbeta8 + deliver.c: + fix on free() problem (in case of LMTP; around smtpgetstat()) + reported by Fumitoshi UKAI + + Oct. 31, 1997/8.8.8+3.0Wbeta7 + readcf.c: + value of O_MAXSENDRCPT + deliver.c: + behavior with mailer flag ! + + Oct. 27, 1997/8.8.8+3.0Wbeta5 + sendmail.h, readcf.c, deliver.c: + mailer flag '!' and '-' added + *= equate added + mailer flag '2' removed + + Oct. 26, 1997/8.8.8+3.0Wbeta4 + applied to 8.8.8 + usersmtp.c: + to manage LMTP response messages corrently + + Oct. 24, 1997/8.8.7+3.0Wbeta3 + deliver.c, sendmail.h: + mailer flag 2 added + readcf.c, deliver.c: + MaxSendRcptPerMessage added + + Oct. 15, 1997/8.8.7+3.0Wbeta1 + features (ANOTHER_MXPB, RCPT_NEXT, CONNECT_HACK, RESOLV_HACK, + STAT_HACK) deleted. + + + Aug. 20, 1997/8.8.7+2.7Wbeta7 + deliver.c: + fix on syslog bufsize boundary problem + suggested by Kenji Ikeda + + Aug. 17, 1997/8.8.7+2.7Wbeta6 + deliver.c: + fix on parameter mismatch for sm_syslog() + reported by Makoto MATSUSHITA + + Aug. 15, 1997/8.8.7+2.7Wbeta5 + deliver.c: + counter implemented to restrict number of recipients less + than 101. + applied to 8.8.7 + + Feb. 2, 1997/8.8.5+2.7Wbeta5 + deliver.c: + declare resethostsignature() at out side of funtions. + clear QDONTSEND flag when QQUEUEUP set + applied to 8.8.5 + + Dec. 4, 1996/8.8.4+2.7Wbeta4 + deliver.c: LOCAL_FIRST added + again: compile failed if ANOTHER_MXPB && DYNAMIC_TOBUF + + Dec. 4, 1996/8.8.4+2.7Wbeta3 + deliver.c: algorithm changed for bufsize limitation checking + compile failed if ANOTHER_MXPB && DYNAMIC_TOBUF + + Dec. 4, 1996/8.8.4+2.7Wbeta2 + deliver.c: fix on dumping core when local delivery + + Dec. 3, 1996/8.8.4+2.7Wbeta1 + applied to 8.8.4 + DYNAMIC_TOBUF hack is added in deliver.c. + + Nov. 18, 1996/8.8.3+2.6Wbeta9-pre + applied to 8.8.3 + + Oct. 27, 1996/8.8.2+2.6Wbeta9 + applied to 8.8.2 + /usr/bsd added to PATH in newvers.sh + res_send.c is replaced by one in bind4.9.4-P1 + static function decl. is moved to outside of a func. + in domain.c, deliver.c + + Sep. 19, 1996/8.7.6+2.6Wbeta8 + applied to 8.7.6 + + Jul. 3, 1996/8.7.5+2.6Wbeta7 + fix on DNS_AR_HACK in savemail.c and domain.c + reported by Shigeki Yoshida + tweaks on res_send.c for .nomx in Patch-makefiles + reported bu y-koga@ccs.mt.nec.co.jp + + Apr. 18, 1996/8.7.5+2.6Wbeta6 + applied to 8.7.5 + + Feb. 23, 1996/8.7.4+2.6Wbeta6 + applied to 8.7.4 + + Jan. 26, 1996/8.7.3+2.6Wbeta5 + applied to 8.7.3 + fix CONNECT_HACK to use all multiple A records + + Oct. 21, 1995/8.7.1+2.6Wbeta4 + applied to 8.7.1 + + Oct. 11, 1995/8.7+2.6Wbeta4 + fix on MULTIMAILER hack + + Sep. 26, 1995/8.7+2.6Wbeta2 + flag bit for RES_NONBLOCK is changed + + Sep. 25, 1995/8.7+2.6Wbeta2 + turn off CANON_OTHER flag if NAMED_BIND == 0 + + Sep. 20, 1995/8.7+2.6Wbeta + Beta release *** sendmail/alias.c.ORG Wed Oct 25 03:04:09 2006 --- sendmail/alias.c Wed Aug 1 16:32:19 2007 *************** *** 164,175 **** --- 164,184 ---- ** Look for owner of alias */ + #if OO_NULLSENDER + if (strcmp(a->q_user, "owner-owner") == 0) + owner = "<>"; + else + { + #endif if (strncmp(a->q_user, "owner-", 6) == 0 || strlen(a->q_user) > sizeof(obuf) - 7) (void) sm_strlcpy(obuf, "owner-owner", sizeof(obuf)); else (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user); owner = aliaslookup(obuf, &status, a->q_host); + #if OO_NULLSENDER + } + #endif if (owner == NULL) return; *** sendmail/collect.c.ORG Wed Nov 29 09:20:40 2006 --- sendmail/collect.c Wed Aug 1 17:37:47 2007 *************** *** 882,892 **** } else { /* if it claimed to be 8 bits, well, it lied.... */ if (e->e_bodytype != NULL && sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) e->e_bodytype = "7BIT"; ! } if (SuperSafe == SAFE_REALLY && !bitset(EF_FATALERRS, e->e_flags)) { --- 882,931 ---- } else { + #if CTE8CHECK + char *p, buf[MAXLINE]; + #endif /* if it claimed to be 8 bits, well, it lied.... */ if (e->e_bodytype != NULL && sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) e->e_bodytype = "7BIT"; ! #if CTE8CHECK ! p = hvalue("Content-Transfer-Encoding", e->e_header); ! if (CTE8BitCheck != NULL && bitset(EF_IS_MIME, e->e_flags) && ! p != NULL && (sm_strcasecmp(p, "8bit") == 0)) ! { ! HDR *h; ! ! switch (*CTE8BitCheck) { ! case 'c': /* correct */ ! for (h = e->e_header; h != NULL; h = h->h_link) ! { ! if (sm_strcasecmp(h->h_field, "Content-Transfer-Encoding") == 0) ! { ! if (h->h_value != NULL) ! free(h->h_value); ! h->h_value = newstr("7bit"); ! } ! } ! sm_snprintf(buf, sizeof buf, ! "Content-Transfer-Encoding from 8bit to 7bit by %s id %s", ! MyHostName, e->e_id); ! ! addheader("X-MIME-Autoconverted:", buf, 0, e, true); ! break; ! case 'r': /* reject */ ! e->e_status = "5.6.1"; ! usrerrenh(e->e_status, "554 Seven bit data with eight bit label not allowed"); ! #if 1 ! sm_syslog(LOG_NOTICE, e->e_id, ! "seven bit data with eight bit label not allowed"); ! #endif ! break; ! } ! } ! ! #endif ! } if (SuperSafe == SAFE_REALLY && !bitset(EF_FATALERRS, e->e_flags)) { *** sendmail/conf.c.ORG Wed Apr 4 06:32:29 2007 --- sendmail/conf.c Wed Aug 1 16:28:43 2007 *************** *** 593,598 **** --- 593,604 ---- map_parseargs, text_map_open, null_map_close, text_map_lookup, null_map_store); + #if MASKED_ADDR + MAPDEF("maskedaddr", NULL, MCF_ALIASOK, + map_parseargs, maskedaddr_map_open, null_map_close, + maskedaddr_map_lookup, null_map_store); + #endif + MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY, map_parseargs, stab_map_open, null_map_close, stab_map_lookup, stab_map_store); *************** *** 5795,5800 **** --- 5801,5845 ---- #if XLA "XLA", #endif /* XLA */ + #if QUICK_RESPONSE + "QUICK_RESPONSE", + #endif + #if MULTI_MAILER + "MULTI_MAILER", + #endif + #if MAILER_PREF + "MAILER_PREF", + #endif + #if CLIENT_SMTP_CONFIG + "CLIENT_SMTP_CONFIG", + #endif + #if CTE8CHECK + "CTE8CHECK", + #endif + #if OO_NULLSENDER + "OO_NULLSENDER", + #endif + #if CF_ALIASING + "CF_ALIASING", + #endif + #if MF_SEPARATE + "MF_SEPARATE", + #endif + #if MASKED_ADDR + "MASKED_ADDR", + #endif + #if SPR_CON_CACHE + "SPR_CON_CACHE", + #endif + #if FORWARDPROGCTL + "FORWARDPROGCTL", + #endif + #if MAILER_TIMEOUTS + "MAILER_TIMEOUTS", + #endif + #if CHECK_WARNING + "CHECK_WARNING", + #endif NULL }; *** sendmail/conf.h.ORG Wed Nov 29 09:36:06 2006 --- sendmail/conf.h Wed Aug 1 16:28:43 2007 *************** *** 42,47 **** --- 42,67 ---- # include # include + /* ================== Enhancements of WIDE version ================== */ + # define QUICK_RESPONSE 1 /* not queue up error response even with -odq */ + # define MULTI_MAILER 1 /* enable multiple mailer dispatching feature */ + # define MAILER_PREF 1 /* enable mailer preference configuration */ + # define CLIENT_SMTP_CONFIG 1 /* enable configuration for SMTP client */ + # define CTE8CHECK 1 /* enable incorrect CTE: 8bit checking */ + # define OO_NULLSENDER 1 /* set NULL sender for owner-owner */ + # define CF_ALIASING 1 /* enable aliasing in ruleset 5 */ + # define MF_SEPARATE 1 /* enable mailerflag + not to suppress dups */ + # define MASKED_ADDR 1 /* enable masked class matching/maskaddr map */ + # define SPR_CON_CACHE 1 /* enable mailerflag ; not to cache conn. */ + # define FORWARDPROGCTL 1 /* control forwarding to program on .forward */ + # define MAILER_TIMEOUTS 1 /* timeouts configuration par mailer */ + # define CHECK_WARNING 1 /* use ruleset for decision on delay warning */ + # define RCPT_HASH 1 /* use hash to check address duplicates */ + /* =========================== parameters =========================== */ + /* for MULTI_MAILER */ + # define MAXDSPTMAILERS 3 /* max # of dispatching mailers in one rule */ + /* ==================================================================== */ + /* make sure TOBUFSIZ isn't larger than system limit for size of exec() args */ #ifdef ARG_MAX # if ARG_MAX > 4096 *** sendmail/deliver.c.ORG Fri Mar 30 06:20:15 2007 --- sendmail/deliver.c Wed Aug 1 18:04:07 2007 *************** *** 784,789 **** --- 784,793 ---- int mode; { register ADDRESS *q; + #if MAILER_PREF + ADDRESS *qnext, *newqhead, *qq, *qqlast; + int i; + #endif bool didany; if (tTd(13, 10)) *************** *** 877,882 **** --- 881,1001 ---- e->e_sibling = oldsib; } + #if MAILER_PREF + /* move more un-prefered recipients later */ + for (i = 0; i < MAXMAILERS; i++) + { + if (Mailer[i] != NULL) + { + Mailer[i]->m_addrtail = NULL; + Mailer[i]->m_addrhead = NULL; + } + } + newqhead = NULL; + + for (q = e->e_sendqueue; q != NULL; q = qnext) + { + qnext = q->q_next; + + if (newqhead == NULL) + { + /* first recipient */ + newqhead = q; + q->q_mailer->m_addrtail = q; + q->q_mailer->m_addrhead = q; + q->q_next = NULL; + } + else if (q->q_mailer->m_addrtail == NULL) + { + /* only for the first recipient of the mailer */ + /* finding insertion point */ + q->q_mailer->m_addrtail = q; + q->q_mailer->m_addrhead = q; + for (qqlast = NULL, qq = newqhead; qq != NULL; + qqlast = qq, qq = qq->q_next) + { + if (qq->q_mailer == q->q_mailer) + { + /* skip to the tail */ + qq = q->q_mailer->m_addrtail; + continue; + } + if (qq->q_mailer->m_pref > q->q_mailer->m_pref) + break; + } + if (qq == NULL) + q->q_next = NULL; /* append at the tail */ + else + { + q->q_next = qq; + } + if (qq == newqhead) + newqhead = q; + else + qqlast->q_next = q; + } + else if (bitnset(M_SORT, q->q_mailer->m_flags)) + { + /* insert in order */ + + qqlast = NULL; + /* XXX lenear search should be avoided */ + for (qq = q->q_mailer->m_addrhead;; qq = qq->q_next) + { + if (sm_strrevcasecmp(q->q_user, qq->q_user) < 0) + break; + if (qq == q->q_mailer->m_addrtail) + { + qq = NULL; + break; + } + qqlast = qq; + } + + if (qq == NULL) + { + /* append at the tail */ + q->q_next = q->q_mailer->m_addrtail->q_next; + q->q_mailer->m_addrtail->q_next = q; + q->q_mailer->m_addrtail = q; + } + else if (qqlast == NULL) + { + /* insert at the head */ + q->q_next = q->q_mailer->m_addrhead; + q->q_mailer->m_addrhead = q; + if (newqhead == q->q_next) + newqhead = q; + else for (i = 0; i < MAXMAILERS; i++) + { + if (Mailer[i] != NULL && + Mailer[i]->m_addrtail != NULL && + Mailer[i]->m_addrtail->q_next == qq) + { + Mailer[i]->m_addrtail->q_next + = q; + break; + } + } + } + else + { + /* insert after *qqlast */ + q->q_next = qqlast->q_next; + qqlast->q_next = q; + } + } + else + { + /* just insert */ + q->q_next = q->q_mailer->m_addrtail->q_next; + q->q_mailer->m_addrtail->q_next = q; + q->q_mailer->m_addrtail = q; + } + } + e->e_sendqueue = newqhead; + #endif + /* now run through the queue */ for (q = e->e_sendqueue; q != NULL; q = q->q_next) { *************** *** 892,897 **** --- 1011,1029 ---- e->e_to = q->q_paddr; if (QS_IS_SENDABLE(q->q_state)) { + #if MAILER_PREF + if (q->q_host != NULL && q->q_host[0] != '\0') + message("deliverable: mailer %s (pref=%d), host %s, user %s", + q->q_mailer->m_name, + q->q_mailer->m_pref, + q->q_host, + q->q_user); + else + message("deliverable: mailer %s (pref=%d), user %s", + q->q_mailer->m_name, + q->q_mailer->m_pref, + q->q_user); + #else if (q->q_host != NULL && q->q_host[0] != '\0') message("deliverable: mailer %s, host %s, user %s", q->q_mailer->m_name, *************** *** 901,906 **** --- 1033,1039 ---- message("deliverable: mailer %s, user %s", q->q_mailer->m_name, q->q_user); + #endif } } else if (QS_IS_OK(q->q_state)) *************** *** 1333,1338 **** --- 1466,1475 ---- char buf[MAXNAME + 1]; char cbuf[MAXPATHLEN]; + #if MULTI_MAILER + retry_deliver: /* retry on next MX/mailer */ + #endif + errno = 0; SM_REQUIRE(firstto != NULL); /* same as to */ if (!QS_IS_OK(to->q_state)) *************** *** 1574,1581 **** --- 1711,1723 ---- ** Check also for overflow of e_msgsize. */ + #if MULTI_MAILER + if (to->q_mailers[1] == NULL && m->m_maxsize != 0 && + (e->e_msgsize > m->m_maxsize || e->e_msgsize < 0)) + #else if (m->m_maxsize != 0 && (e->e_msgsize > m->m_maxsize || e->e_msgsize < 0)) + #endif { e->e_flags |= EF_NO_BODY_RETN; if (bitnset(M_LOCALMAILER, to->q_mailer->m_flags)) *************** *** 1796,1801 **** --- 1938,1983 ---- } } + #if MULTI_MAILER + if (firstto->q_mailers[1] != NULL) + { + if (firstto->q_mailer->m_rmin > 0 + && rcptcount < firstto->q_mailer->m_rmin) + { + /* skip to next mailer */ + sm_syslog(LOG_INFO, e->e_id, + "skip mailer: recipients = %d", rcptcount); + mci = NULL; + goto nextmailer; + } + if (firstto->q_mailer->m_maxsize != 0 + && e->e_msgsize > firstto->q_mailer->m_maxsize) + { + /* skip to next mailer */ + sm_syslog(LOG_INFO, e->e_id, + "skip mailer: message size = %d", e->e_msgsize); + mci = NULL; + goto nextmailer; + } + if (bitnset(M_DIRECTONLY, firstto->q_mailer->m_flags) + && e->e_ntries > 0) + { + /* skip to next mailer */ + sm_syslog(LOG_INFO, e->e_id, + "skip mailer: retry count = %d", e->e_ntries); + mci = NULL; + goto nextmailer; + } + } + if (bitnset(M_NONEXT, firstto->q_mailer->m_flags)) + { + for (to = tochain; to != NULL; to = to->q_tchain) + { + to->q_mailers[1] = NULL; + } + } + #endif + /* see if any addresses still exist */ if (tochain == NULL) { *************** *** 2181,2186 **** --- 2363,2371 ---- goodmxfound = true; markstats(e, firstto, STATS_CONNECT); mci->mci_state = MCIS_OPENING; + #if SPR_CON_CACHE + if (!bitnset(M_NOCACHE, m->m_flags)) + #endif mci_cache(mci); if (TrafficLogFile != NULL) (void) sm_io_fprintf(TrafficLogFile, *************** *** 2735,2740 **** --- 2920,2957 ---- (void) setsid(); # endif /* !_FFR_USE_SETLOGIN */ + #if 1 /* to pass some information to SMTPfeed */ + { + char lbuf[32]; + sm_snprintf(lbuf, sizeof(lbuf), "%d", e->e_stime); + sm_setuserenv("SM_START_TIME", lbuf); + } + #endif + #if 1 /* to see real local addresses */ + if (LogLevel > 9) + { + char execstr[SYSLOG_BUFSIZE]; + char **p = pv; + int l; + + strncpy(execstr, pv[0], sizeof(execstr) - 4); + if (strlen(pv[0]) >= sizeof(execstr) - 4) + execstr[sizeof(execstr)-1] = '\0'; + l = strlen(execstr); + p++; + while (*p != NULL && + l + strlen(*p) + 1 <= sizeof(execstr) - 4) + { + execstr[l++] = ' '; + strcpy(execstr + l, *p); + l += strlen(*p); + p++; + } + if (*p != NULL) + strcpy(execstr + l, " ..."); + sm_syslog(LOG_INFO, e->e_id, "EXEC: %s", execstr); + } + #endif /* try to execute the mailer */ (void) execve(m->m_mailer, (ARGV_T) pv, (ARGV_T) UserEnviron); *************** *** 2776,2781 **** --- 2993,3001 ---- if (clever) { mci->mci_state = MCIS_OPENING; + #if SPR_CON_CACHE + if (!bitnset(M_NOCACHE, m->m_flags)) + #endif mci_cache(mci); } else *************** *** 3602,3607 **** --- 3822,3878 ---- } #endif /* 0 */ } + # if MULTI_MAILER + else + { + bool mailer_changed; + int i; + + nextmailer: + mailer_changed = false; + if (firstto->q_mailers[1] != NULL) + { + mailer_changed = true; + } + for (to = tochain; to != NULL; to = to->q_tchain) + { + if (to->q_mailers[1] != NULL) { + to->q_state = QS_OK; + /* change to next mailer */ + for (i = 0; i < MAXDSPTMAILERS - 1; i++) + { + to->q_mailers[i] = to->q_mailers[i+1]; + to->q_hosts[i] = to->q_hosts[i+1]; + to->q_users[i] = to->q_users[i+1]; + } + to->q_mailers[MAXDSPTMAILERS-1] = NULL; + to->q_hosts[MAXDSPTMAILERS-1] = NULL; + to->q_users[MAXDSPTMAILERS-1] = NULL; + } + else if (mailer_changed) + { + markfailure(e, to, mci, rcode, true); + } + /* if not changed, will be done later */ + } + if (mailer_changed) + { + mci_store_persistent(mci); + #if SMTP + /* now close the connection */ + if (clever && mci != NULL && + mci->mci_state != MCIS_CLOSED && + !bitset(MCIF_CACHED, mci->mci_flags)) + smtpquit(m, mci, e); + #endif + /* re-initialize variables */ + to = firstto; + clever = false; + tochain = NULL; + goto retry_deliver; + } + } + # endif if (anyok) markstats(e, tochain, STATS_NORMAL); mci_store_persistent(mci); *** sendmail/envelope.c.ORG Sat Nov 11 08:12:52 2006 --- sendmail/envelope.c Wed Aug 1 18:03:38 2007 *************** *** 179,184 **** --- 179,188 ---- char *id = e->e_id; time_t now; char buf[MAXLINE]; + #if MAILER_TIMEOUTS + bool no_expire = false; + int to_r = 0; + #endif if (tTd(50, 1)) { *************** *** 218,225 **** --- 222,231 ---- */ now = curtime(); + #if !MAILER_TIMEOUTS if (now >= e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) msg_timeout = MSG_T_O; + #endif if (IS_DLVR_RETURN(e) && e->e_deliver_by > 0 && now >= e->e_ctime + e->e_deliver_by && !bitset(EF_RESPONSE, e->e_flags)) *************** *** 237,242 **** --- 243,260 ---- e->e_flags &= ~EF_QUEUERUN; for (q = e->e_sendqueue; q != NULL; q = q->q_next) { + #if MAILER_TIMEOUTS + int to1; + + if (q->q_mailer->m_to_q_return > 0) + to1 = q->q_mailer->m_to_q_return; + else + to1 = TimeOuts.to_q_return[e->e_timeoutclass]; + if (!IS_MSG_ERR(msg_timeout) && curtime() > e->e_ctime + to1) + msg_timeout = MSG_T_O; + else + no_expire = true; + #endif if (QS_IS_UNDELIVERED(q->q_state)) queueit = true; *************** *** 255,260 **** --- 273,282 ---- &e->e_errorqueue, 0, e); done = true; } + #if MAILER_TIMEOUTS + if (to_r < to1) + to_r = to1; + #endif } else if ((bitset(QPINGONSUCCESS, q->q_flags) && ((QS_IS_SENT(q->q_state) && *************** *** 288,303 **** --- 310,336 ---- e->e_deliver_by); } else + #if MAILER_TIMEOUTS + { + (void) sm_snprintf(buf, sizeof(buf), + "Cannot send message for %s", + pintvl(to_r, false)); + } + #else { (void) sm_snprintf(buf, sizeof(buf), "Cannot send message for %s", pintvl(TimeOuts.to_q_return[e->e_timeoutclass], false)); } + #endif /* don't free, allocated from e_rpool */ e->e_message = sm_rpool_strdup_x(e->e_rpool, buf); message(buf); + #if MAILER_TIMEOUTS + if (!no_expire) + #endif e->e_flags |= EF_CLRQUEUE; } if (msg_timeout == MSG_NOT_BY) *************** *** 307,320 **** --- 340,373 ---- e->e_deliver_by); } else + #if MAILER_TIMEOUTS + (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, + "Message could not be delivered for %s\n", + pintvl(to_r, false)); + #else (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, "Message could not be delivered for %s\n", pintvl(TimeOuts.to_q_return[e->e_timeoutclass], false)); + #endif + #if MAILER_TIMEOUTS + if (!no_expire) + #endif (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, "Message will be deleted from queue\n"); for (q = e->e_sendqueue; q != NULL; q = q->q_next) { + #if MAILER_TIMEOUTS + int to1; + + if (q->q_mailer->m_to_q_return > 0) + to1 = q->q_mailer->m_to_q_return; + else + to1 = TimeOuts.to_q_return[e->e_timeoutclass]; + if (curtime() <= e->e_ctime + to1) + continue; + #endif + if (QS_IS_UNDELIVERED(q->q_state)) { q->q_state = QS_BADADDR; *************** *** 338,351 **** --- 391,418 ---- if (IS_MSG_WARN(msg_timeout)) { + #if CHECK_WARNING + # define OPR 0 /* operator */ + extern u_char ExtTokenTab[]; + u_char savetok = ExtTokenTab['-']; + ExtTokenTab['-'] = OPR; + #endif if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && e->e_class >= 0 && e->e_from.q_paddr != NULL && strcmp(e->e_from.q_paddr, "<>") != 0 && sm_strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 && + #if CHECK_WARNING + (strlen(e->e_from.q_paddr) <= 8 || + sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0) && + (strtorwset("check_warning", NULL, ST_FIND) < 0 || + rscheck("check_warning", e->e_from.q_paddr, NULL, + e, RSF_RMCOMM|RSF_COUNT, 4, NULL, e->e_id, NULL) != EX_OK)) + #else (strlen(e->e_from.q_paddr) <= 8 || sm_strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0)) + #endif { for (q = e->e_sendqueue; q != NULL; q = q->q_next) *************** *** 412,417 **** --- 479,487 ---- "Will keep trying until message is %s old\n", pintvl(TimeOuts.to_q_return[e->e_timeoutclass], false)); + #if CHECK_WARNING + ExtTokenTab['-'] = savetok; + #endif } } *************** *** 742,747 **** --- 812,820 ---- openxscript(e); e->e_ctime = curtime(); + #if 1 /* start time of sendmail to pass to SMTPfeed for statistics */ + e->e_stime = e->e_ctime; + #endif e->e_qfletter = '\0'; /* *** sendmail/headers.c.ORG Thu Feb 8 07:44:35 2007 --- sendmail/headers.c Wed Aug 1 16:28:43 2007 *************** *** 839,846 **** --- 839,852 ---- } /* do early binding */ + #if 1 /* do not bind $h early */ + if (bitset(H_DEFAULT, h->h_flags) && + !bitset(H_BINDLATE, h->h_flags) && + strstr("\201h", h->h_value) == NULL) + #else if (bitset(H_DEFAULT, h->h_flags) && !bitset(H_BINDLATE, h->h_flags)) + #endif { if (tTd(32, 1)) { *** sendmail/map.c.ORG Wed Apr 4 06:33:14 2007 --- sendmail/map.c Wed Aug 1 16:28:43 2007 *************** *** 7108,7113 **** --- 7108,7387 ---- return regex_map_rewrite(map, "", (size_t)0, av); } #endif /* MAP_REGEX */ + #if MASKED_ADDR + /* + ** MASKED ADDR (IP address with mask matching) Modules + */ + + + /* + ** MASKEDADDR_MAP_OPEN + */ + + bool + maskedaddr_map_open(map, mode) + MAP *map; + int mode; + { + int sff; + int i; + + if (tTd(38, 2)) + sm_dprintf("maskedaddr_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + + mode &= O_ACCMODE; + if (mode != O_RDONLY) + { + errno = EPERM; + return false; + } + + if (*map->map_file == '\0') + { + syserr("maskedaddr map \"%s\": file name required", + map->map_mname); + return false; + } + + if (map->map_file[0] != '/') + { + syserr("maskedaddr map \"%s\": file name must be fully qualified", + map->map_mname); + return false; + } + + sff = SFF_ROOTOK|SFF_REGONLY; + if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) + sff |= SFF_NOWLINK; + if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) + sff |= SFF_SAFEDIRPATH; + if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, + sff, S_IRUSR, NULL)) != 0) + { + /* cannot open this map */ + if (tTd(38, 2)) + sm_dprintf("\tunsafe map file: %d\n", i); + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("maskedaddr map \"%s\": unsafe map file %s", + map->map_mname, map->map_file); + return false; + } + + if (bitset(MF_NODEFER, map->map_mflags)) + { + if (maskedaddr_build(map) == false) + return false; + } + + map->map_sff = sff; + return true; + } + + struct addr_list { + struct addr_list *next; + SOCKADDR addr; + int masklen; + char *val; + }; + + /* + ** MASKEDADDR_MAP_LOOKUP + */ + + char * + maskedaddr_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; + { + bool found_it; + struct addr_list *alp, *alpnext; + SOCKADDR sa; + char *vp; + auto int vsize; + + if (!bitset(MF_NODEFER, map->map_mflags)) + { + if ((alp = (struct addr_list*)map->map_rebuild) != NULL) + { + alpnext = alp->next; + free(alp); + alp = alpnext; + map->map_rebuild = NULL; + } + + if (maskedaddr_build(map) == false) + { + *statp = EX_UNAVAILABLE; + return NULL; + } + } + + if (tTd(38, 20)) + sm_dprintf("maskedaddr_map_lookup(%s, %s)\n", + map->map_mname, name); + + memset(&sa, '\0', sizeof(sa)); + if (anynet_aton(name, &sa) == 0) + { + if (tTd(38, 20)) + sm_dprintf("maskedaddr_map_lookup: invalid address format\n"); + *statp = EX_NOTFOUND; + return NULL; + } + + alp = (struct addr_list*)map->map_rebuild; + while (alp != NULL) + { + if (alp->addr.sa.sa_family != sa.sa.sa_family) + { + alp = alp->next; + continue; + } + if (maskedaddrcmp(&sa, &alp->addr, alp->masklen) == 0) + { + if (tTd(38, 20)) + sm_dprintf("maskedaddr_map_lookup: found %s\n", + alp->val); + *statp = EX_OK; + vp = alp->val; + vsize = strlen(vp); + if (bitset(MF_MATCHONLY, map->map_mflags)) + return map_rewrite(map, name, strlen(name), + NULL); + else + return map_rewrite(map, vp, vsize, av); + } + alp = alp->next; + } + + *statp = EX_NOTFOUND; + return NULL; + } + + bool + maskedaddr_build(map) + MAP *map; + { + SM_FILE_T *f; + int sff = map->map_sff; + char linebuf[MAXLINE]; + SOCKADDR sa; + int masklen; + struct addr_list *alp, *alp2, *alp3; + + f = safefopen(map->map_file, O_RDONLY, FileMode, sff); + if (f == NULL) + { + map->map_mflags &= ~(MF_VALID|MF_OPEN); + return false; + } + + while (sm_io_fgets(f, SM_TIME_DEFAULT, linebuf, MAXLINE) != NULL) + { + char *p, *q; + + /* skip comment line */ + if (linebuf[0] == '#') + continue; + p = strchr(linebuf, '\n'); + if (p != NULL) + *p = '\0'; + masklen = -1; + p = strchr(linebuf, '/'); + if (p != NULL) + { + *p++ = '\0'; + q = p; + while (isdigit(*q)) + q++; + if (*q != '\0' && !isspace(*q)) + { + /* ignore it */ + continue; + } + *q++ = '\0'; + masklen = atoi(p); + } + else + { + q = linebuf; + while (*q != '\0' && !isspace(*q)) + q++; + *q++ = '\0'; + } + while (isspace(*q)) + q++; + + memset(&sa, '\0', sizeof(sa)); + if (anynet_aton(linebuf, &sa) > 0) + { + alp = (struct addr_list*)xalloc(sizeof(struct addr_list)); + memset(alp, '\0', sizeof(struct addr_list)); + alp->addr.sa.sa_family = sa.sa.sa_family; + switch (sa.sa.sa_family) + { + case AF_INET: + alp->addr.sin.sin_addr = sa.sin.sin_addr; + if (masklen < 0 || masklen > 32) + alp->masklen = 32; + else + alp->masklen = masklen; + break; + #if NETINET6 + case AF_INET6: + alp->addr.sin6.sin6_addr = sa.sin6.sin6_addr; + if (masklen < 0 || masklen > 128) + alp->masklen = 128; + else + alp->masklen = masklen; + break; + #endif + } + alp->val = newstr(q); + + if (tTd(38, 20)) + sm_dprintf("maskedaddr_store(%s, %s/%d, %s)\n", + map->map_mname, linebuf, masklen, q); + } + else + continue; + + /* insertion sort (longer mask first) */ + alp2 = (struct addr_list*)map->map_rebuild; + alp3 = NULL; + + if (alp2 == NULL) + { + map->map_rebuild = (char *)alp; + continue; + } + while (alp2 != NULL) + { + if (alp->masklen > alp2->masklen) + { + if (alp3 == NULL) + map->map_rebuild = (char *)alp; + else + alp3->next = alp; + alp->next = alp2; + break; + } + alp3 = alp2; + alp2 = alp2->next; + } + if (alp2 == NULL) + { + alp3->next = alp; + } + } + (void) sm_io_close(f, SM_TIME_DEFAULT); + + return true; + } + #endif /* MASKED_ADDR */ /* ** NSD modules */ *** sendmail/parseaddr.c.ORG Thu Dec 21 09:24:06 2006 --- sendmail/parseaddr.c Wed Aug 1 17:43:58 2007 *************** *** 653,658 **** --- 653,853 ---- ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ONE }; + #if MASKED_ADDR + static int maskedaddrcmp_match; + static SOCKADDR matchingaddr; + + static void + maskedaddrcmp_class(s, id) + register STAB *s; + int id; + { + SOCKADDR matchaddr; + char *p; + int masklen, r; + + if (maskedaddrcmp_match) + return; + if (s->s_symtype != ST_CLASS) + return; + if (bitnset(id & 0xff, s->s_class)) + { + #if NETINET6 + if (strchr(s->s_name, ':') == NULL && !isdigit(*s->s_name)) + #else + if (!isdigit(*s->s_name)) + #endif + return; + p = strchr(s->s_name, '/'); + if (p != NULL) + *p = '\0'; + r = anynet_aton(s->s_name, &matchaddr); + if (p != NULL) + *p = '/'; + if (r == 0) + return; + + if (p != NULL) + masklen = atoi(++p); + else + { + switch (matchaddr.sa.sa_family) + { + case AF_INET: + masklen = 32; + break; + #if NETINET6 + case AF_INET6: + masklen = 128; + break; + #endif + } + } + if (maskedaddrcmp(&matchingaddr, &matchaddr, masklen) == 0) + maskedaddrcmp_match = 1; + } + } + + int + anynet_aton(str, addr) + char *str; + SOCKADDR *addr; + { + char *p; + #if NETINET6 + if (strchr(str, ':') != NULL) + { + /* IPv6 address */ + } + else + #endif + if ((p = strchr(str, '.')) != NULL) + { + /* need quad for IPv4 addr */ + if ((p = strchr(p+1, '.')) == NULL + || (p = strchr(p+1, '.')) == NULL) + return 0; + if (strchr(p+1, '.') != NULL) + return 0; + } + else + return 0; + + memset(addr, '\0', sizeof(SOCKADDR)); + if ((addr->sin.sin_addr.s_addr = inet_addr(str)) != INADDR_NONE) + { + addr->sin.sin_family = AF_INET; + return 1; + } + #if NETINET6 + else if (inet_pton(AF_INET6, str, &addr->sin6.sin6_addr) > 0) + { + addr->sin6.sin6_family = AF_INET6; + return 1; + } + #endif + return 0; + } + + static unsigned long netmask[33] = { + 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, + 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, + 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, + 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, + 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, + 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, + 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, + 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe, + 0xffffffff + }; + + int + maskedaddrcmp(adr1, adr2, masklen) + SOCKADDR *adr1, *adr2; + int masklen; + { + unsigned long a1, a2; + + if (tTd(21, 40)) + { + sm_dprintf("maskedaddrcmp: a1 = %s\n", anynet_ntoa(adr1)); + sm_dprintf("maskedaddrcmp: a2 = %s\n", anynet_ntoa(adr1)); + sm_dprintf("maskedaddrcmp: ml = %d\n", masklen); + } + + if (adr1->sa.sa_family != adr2->sa.sa_family) + return -1; + + switch (adr1->sa.sa_family) + { + case AF_INET: + a1 = ntohl(adr1->sin.sin_addr.s_addr) & netmask[masklen]; + a2 = ntohl(adr2->sin.sin_addr.s_addr) & netmask[masklen]; + if (a1 == a2) + return 0; + break; + #if NETINET6 + case AF_INET6: + if (masklen < 32) + { + a1 = ntohl(((u_long *)&adr1->sin6.sin6_addr)[0]) + & netmask[masklen]; + a2 = ntohl(((u_long *)&adr2->sin6.sin6_addr)[0]) + & netmask[masklen]; + if (a1 == a2) + return 0; + } + else if (masklen < 64) + { + if (((u_long *)&adr1->sin6.sin6_addr)[0] + != ((u_long *)&adr2->sin6.sin6_addr)[0]) + break; + a1 = ntohl(((u_long *)&adr1->sin6.sin6_addr)[1]) + & netmask[masklen-32]; + a2 = ntohl(((u_long *)&adr2->sin6.sin6_addr)[1]) + & netmask[masklen-32]; + if (a1 == a2) + return 0; + } + else if (masklen < 96) + { + if (((u_long *)&adr1->sin6.sin6_addr)[0] + != ((u_long *)&adr2->sin6.sin6_addr)[0]) + break; + if (((u_long *)&adr1->sin6.sin6_addr)[1] + != ((u_long *)&adr2->sin6.sin6_addr)[1]) + break; + a1 = ntohl(((u_long *)&adr1->sin6.sin6_addr)[2]) + & netmask[masklen-64]; + a2 = ntohl(((u_long *)&adr2->sin6.sin6_addr)[2]) + & netmask[masklen-64]; + if (a1 == a2) + return 0; + } + else + { + if (((u_long *)&adr1->sin6.sin6_addr)[0] + != ((u_long *)&adr2->sin6.sin6_addr)[0]) + break; + if (((u_long *)&adr1->sin6.sin6_addr)[1] + != ((u_long *)&adr2->sin6.sin6_addr)[1]) + break; + if (((u_long *)&adr1->sin6.sin6_addr)[2] + != ((u_long *)&adr2->sin6.sin6_addr)[2]) + break; + a1 = ntohl(((u_long *)&adr1->sin6.sin6_addr)[3]) + & netmask[masklen-96]; + a2 = ntohl(((u_long *)&adr2->sin6.sin6_addr)[3]) + & netmask[masklen-96]; + if (a1 == a2) + return 0; + } + break; + #endif + } + return -1; + } + #endif #define NOCHAR (-1) /* signal nothing in lookahead token */ *************** *** 1115,1120 **** --- 1310,1318 ---- while ((ap = *avp) != NULL || *rvp != NULL) { + #if MASKED_ADDR + bool maskedaddr_match; + #endif rp = *rvp; if (tTd(21, 35)) { *************** *** 1141,1146 **** --- 1339,1351 ---- { case MATCHCLASS: /* match any phrase in a class */ + #if MASKED_ADDR + if (wordinclass("_MASKED_ADDRESS_MATCH_", + rp[1])) + maskedaddr_match = 1; + else + maskedaddr_match = 0; + #endif mlp->match_pattern = rvp; mlp->match_first = avp; extendclass: *************** *** 1150,1155 **** --- 1355,1385 ---- mlp->match_last = avp++; cataddr(mlp->match_first, mlp->match_last, buf, sizeof(buf), '\0', true); + #if MASKED_ADDR + if (maskedaddr_match + && anynet_aton(buf, &matchingaddr) > 0) + { + if (tTd(21, 40)) + sm_dprintf("maskedaddr check: %s\n", buf); + + maskedaddrcmp_match = 0; + stabapply(maskedaddrcmp_class, rp[1]); + + if (!maskedaddrcmp_match) + { + if (tTd(21, 36)) + { + sm_dprintf("EXTEND rp="); + xputs(sm_debug_file(), rp); + sm_dprintf(", ap="); + xputs(sm_debug_file(), ap); + sm_dprintf("\n"); + } + goto extendclass; + } + } + else + #endif if (!wordinclass(buf, rp[1])) { if (tTd(21, 36)) *************** *** 1962,1967 **** --- 2192,2202 ---- char **hostp; char hbuf[MAXNAME + 1]; static char ubuf[MAXNAME + 2]; + #if MULTI_MAILER + char **tvnext; + char *tvsave; + int nmailer = 0; + #endif if (tTd(24, 5)) { *************** *** 1978,1983 **** --- 2213,2236 ---- /* set up default error return flags */ a->q_flags |= DefaultNotify; + #if MULTI_MAILER + tvnext = tv; + do { + while (*++tvnext != NULL) + { + if ((**tvnext & 0377) == CANONNET) + { + break; + } + } + if (*tvnext != NULL) + { + tvsave = *tvnext; + *tvnext = NULL; + } else { + tvnext = NULL; + } + #endif /* figure out what net/mailer to use */ if (*tv == NULL || (**tv & 0377) != CANONNET) { *************** *** 1999,2005 **** --- 2252,2262 ---- else { a->q_state = QS_BADADDR; + #if MULTI_MAILER + a->q_mailers[nmailer] = &errormailer; + #else a->q_mailer = &errormailer; + #endif } return a; } *************** *** 2112,2118 **** --- 2369,2379 ---- syserr("554 5.3.5 buildaddr: unknown mailer %s", mname); goto badaddr; } + #if MULTI_MAILER + a->q_mailers[nmailer] = m; + #else a->q_mailer = m; + #endif /* figure out what host (if any) */ if (hostp == NULL) *************** *** 2122,2131 **** --- 2383,2400 ---- syserr("554 5.3.5 buildaddr: no host"); goto badaddr; } + #if MULTI_MAILER + a->q_hosts[nmailer] = NULL; + #else a->q_host = NULL; + #endif } else + #if MULTI_MAILER + a->q_hosts[nmailer] = sm_rpool_strdup_x(e->e_rpool, hbuf); + #else a->q_host = sm_rpool_strdup_x(e->e_rpool, hbuf); + #endif /* figure out the user */ p = ubuf; *************** *** 2141,2149 **** --- 2410,2426 ---- if (*p == '"') p++; if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags)) + #if MULTI_MAILER + a->q_mailers[nmailer] = m = ProgMailer; + #else a->q_mailer = m = ProgMailer; + #endif else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags)) + #if MULTI_MAILER + a->q_mailers[nmailer] = m = FileMailer; + #else a->q_mailer = m = FileMailer; + #endif else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags)) { /* may be :include: */ *************** *** 2151,2164 **** --- 2428,2451 ---- if (sm_strncasecmp(ubuf, ":include:", 9) == 0) { /* if :include:, don't need further rewriting */ + #if MULTI_MAILER + a->q_mailers[nmailer] = m = InclMailer; + a->q_users[nmailer] = sm_rpool_strdup_x(e->e_rpool, + &ubuf[9]); + #else a->q_mailer = m = InclMailer; a->q_user = sm_rpool_strdup_x(e->e_rpool, &ubuf[9]); + #endif return a; } } /* rewrite according recipient mailer rewriting rules */ + #if MULTI_MAILER + macdefine(&e->e_macro, A_PERM, 'h', a->q_hosts[nmailer]); + #else macdefine(&e->e_macro, A_PERM, 'h', a->q_host); + #endif if (ConfigLevel >= 10 || !bitset(RF_SENDERADDR|RF_HEADERADDR, flags)) *************** *** 2172,2193 **** --- 2459,2500 ---- /* save the result for the command line/RCPT argument */ cataddr(tv, NULL, ubuf, sizeof(ubuf), '\0', true); + #if MULTI_MAILER + a->q_users[nmailer] = sm_rpool_strdup_x(e->e_rpool, ubuf); + #else a->q_user = sm_rpool_strdup_x(e->e_rpool, ubuf); + #endif /* ** Do mapping to lower case as requested by mailer */ + #if MULTI_MAILER + if (a->q_hosts[nmailer] != NULL && !bitnset(M_HST_UPPER, m->m_flags)) + makelower(a->q_hosts[nmailer]); + if (!bitnset(M_USR_UPPER, m->m_flags)) + makelower(a->q_users[nmailer]); + #else if (a->q_host != NULL && !bitnset(M_HST_UPPER, m->m_flags)) makelower(a->q_host); if (!bitnset(M_USR_UPPER, m->m_flags)) makelower(a->q_user); + #endif if (tTd(24, 6)) { sm_dprintf("buildaddr => "); printaddr(sm_debug_file(), a, false); } + #if MULTI_MAILER + if (tvnext != NULL) + { + *tvnext = tvsave; + tv = tvnext; + nmailer++; + } + } while (tvnext && (nmailer < MAXDSPTMAILERS)); + #endif return a; } *************** *** 2860,2865 **** --- 3167,3190 ---- SM_END_TRY /* if non-null, mailer destination specified -- has it changed? */ + #if CF_ALIASING + if (a1 != NULL && a1->q_mailer != NULL && + bitnset(M_LOCALMAILER, a1->q_mailer->m_flags) && + a1->q_host != NULL && sm_strcasecmp(a1->q_host, "alias") == 0) + { + /* aliasing mode */ + + /* mark old address as dead; insert new address */ + + a->q_state = QS_REPLACED; + (void) sendtolist(a1->q_user, a, sendq, aliaslevel + 1, e); + if (bitset(QSELFREF, a->q_flags) && + !bitset(QPRIMARY, a->q_flags)) + a->q_state = QS_OK; + + return; + } + #endif if (a1 == NULL || sameaddr(a, a1)) { if (tTd(29, 9)) *** sendmail/readcf.c.ORG Fri Oct 6 05:58:59 2006 --- sendmail/readcf.c Wed Aug 1 16:51:26 2007 *************** *** 1203,1208 **** --- 1203,1213 ---- char fcode; auto char *endp; static int nextmailer = 0; /* "free" index into Mailer struct */ + #if CLIENT_SMTP_CONFIG + char *c_fqdn, *c_addr; + int c_family, c_port; + struct client_config *ccnf; + #endif /* allocate a mailer and set up defaults */ m = (struct mailer *) xalloc(sizeof(*m)); *************** *** 1480,1485 **** --- 1485,1686 ---- m->m_rootdir = newstr(p); break; + #if MULTI_MAILER + case '*': /* recipient lower limit */ + m->m_rmin = atoi(p); + break; + #endif + #if MAILER_PREF + case '%': /* mailer preference */ + m->m_pref = atoi(p); + break; + #endif + #if MAILER_TIMEOUTS + case '?': /* mailer preference */ + m->m_to_q_return = atoi(p); + break; + #endif + #if CLIENT_SMTP_CONFIG + case '@': /* client-side SMTP configuration */ + /* Family:FQDN/address/port */ + if (sm_strncasecmp(p, "inet:", 5) == 0) + { + c_family = AF_INET; + p += 5; + } + #if NETINET6 + else if (sm_strncasecmp(p, "inet6:", 6) == 0) + { + c_family = AF_INET6; + p += 6; + } + #endif + else + { + c_family = AF_INET; + } + + if (*p == '\0' || *p == '/') + { + c_fqdn = NULL; + if (*p == '/') + p++; + } + else + { + char *q = strchr(p, '/'); + if (q == NULL) + { + c_fqdn = p; + p += strlen(p); + } + else + { + *q = '\0'; + c_fqdn = p; + p = q + 1; + } + } + + if (*p == '\0' || *p == '/') + { + c_addr = NULL; + if (*p == '/') + p++; + } + else + { + char *q = strchr(p, '/'); + if (q == NULL) + { + c_addr = p; + p += strlen(p); + } + else + { + *q = '\0'; + c_addr = p; + p = q + 1; + } + } + + if (isdigit(*p)) + c_port = atoi(p); + else + c_port = 0; + + if (c_fqdn == NULL && c_addr == NULL) + break; + + ccnf = (struct client_config*) + malloc(sizeof(struct client_config)); + memset(ccnf, '\0', sizeof(ccnf)); + ccnf->next = m->m_ccnf; + m->m_ccnf = ccnf; + + ccnf->addr.sa.sa_family = c_family; + + switch (c_family) + { + case AF_INET: + ccnf->addr.sin.sin_addr.s_addr = INADDR_ANY; + ccnf->addr.sin.sin_port = htons(c_port); + break; + #if NETINET6 + case AF_INET6: + ccnf->addr.sin6.sin6_addr = in6addr_any; + ccnf->addr.sin6.sin6_port = htons(c_port); + break; + #endif + } + + if (c_addr == NULL) + { + /* any address */ + } + else if (strcmp(c_addr, "@") == 0) + { + /* use DNS map for FQDN */ + struct hostent *hp; + + switch (c_family) + { + case AF_INET: + hp = sm_gethostbyname(c_fqdn, AF_INET); + break; + #if NETINET6 + case AF_INET6: + hp = sm_gethostbyname(c_fqdn, AF_INET6); + break; + #endif + } + if (hp != NULL) + { + switch (c_family) + { + case AF_INET: + memmove(&ccnf->addr.sin.sin_addr, hp->h_addr, INADDRSZ); + break; + #if NETINET6 + case AF_INET6: + memmove(&ccnf->addr.sin6.sin6_addr, hp->h_addr, IN6ADDRSZ); + break; + #endif + } + } + else + { + sm_syslog(LOG_NOTICE, NOQID, + "can't resolv %.100s", c_addr); + } + } + else + { + switch (c_family) + { + case AF_INET: + ccnf->addr.sin.sin_addr.s_addr = + inet_addr(c_addr); + break; + #if NETINET6 + case AF_INET6: + inet_pton(AF_INET6, c_addr, &ccnf->addr.sin6.sin6_addr); + break; + #endif + } + } + + if (c_fqdn == NULL) + { + /* use DNS reverse map for ADDR */ + struct hostent *hp; + + switch (c_family) + { + #if NETINET6 + case AF_INET6: + hp = sm_gethostbyaddr((char *)&ccnf->addr.sin6.sin6_addr, IN6ADDRSZ, AF_INET6); + break; + #endif + case AF_INET: + hp = sm_gethostbyaddr((char *)&ccnf->addr.sin.sin_addr, INADDRSZ, AF_INET); + break; + } + if (hp != NULL) + { + ccnf->heloname = newstr(hp->h_name); + } + else + { + sm_syslog(LOG_NOTICE, NOQID, + "can't resolv %.100s", c_addr); + } + } + else + { + ccnf->heloname = newstr(c_fqdn); + } + #endif default: syserr("M%s: unknown mailer equate %c=", m->m_name, fcode); *************** *** 1921,1926 **** --- 2122,2168 ---- xputs(fp, *a++); } } + #if MULTI_MAILER + if (m->m_rmin > 0) + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " *=%d", + m->m_rmin); + #endif + #if MAILER_PREF + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " %%=%d", m->m_pref); + #endif + #if MAILER_TIMEOUTS + if (m->m_to_q_return > 0) + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, " ?=[%s]", + pintvl(m->m_to_q_return, false)); + #endif + #if CLIENT_SMTP_CONFIG + { + struct client_config *ccnf = m->m_ccnf; + while (ccnf != NULL) + { + switch (ccnf->addr.sa.sa_family) + { + case AF_INET: + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + " @=inet:%s/%s/%d", + (ccnf->heloname == NULL)?"":ccnf->heloname, + anynet_ntoa(&ccnf->addr), + ntohs(ccnf->addr.sin.sin_port)); + break; + #if NETINET6 + case AF_INET6: + (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, + " @=inet6:%s/%s/%d", + (ccnf->heloname == NULL)?"":ccnf->heloname, + anynet_ntoa(&ccnf->addr), + ntohs(ccnf->addr.sin6.sin6_port)); + break; + #endif + } + ccnf = ccnf->next; + } + } + #endif (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "\n"); } /* *************** *** 2040,2045 **** --- 2282,2291 ---- { "ForkEachJob", 'Y', OI_NONE }, { "ClassFactor", 'z', OI_NONE }, { "RetryFactor", 'Z', OI_NONE }, + #if CTE8CHECK + #define O_CTE8CHECK 0xf0 + { "CTE8BitCheck", O_CTE8CHECK, OI_SAFE }, + #endif #define O_QUEUESORTORD 0x81 { "QueueSortOrder", O_QUEUESORTORD, OI_SAFE }, #define O_HOSTSFILE 0x82 *************** *** 3321,3326 **** --- 3567,3578 ---- case O_MAXALIASRCSN: MaxAliasRecursion = atoi(val); break; + + #if CTE8CHECK + case O_CTE8CHECK: + CTE8BitCheck = newstr(val); + break; + #endif case O_CNCTONLYTO: /* XXX should probably use gethostbyname */ *** sendmail/recipient.c.ORG Tue Mar 20 06:33:09 2007 --- sendmail/recipient.c Wed Aug 1 16:52:00 2007 *************** *** 23,28 **** --- 23,84 ---- typedef int sortfn_t __P((ADDRESS *, ADDRESS *)); + #if RCPT_HASH + #define HASH_SIZE 2003 + static ADDRESS *addrhash[HASH_SIZE]; + static int use_hash = 0; + static ADDRESS **chainlast; + + void + make_rcpt_hash(sendq, e) + register ADDRESS **sendq; + register ENVELOPE *e; + { + ADDRESS **pq, *q; + int hfunc; + + if (use_hash++ > 0) + return; + + for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next) + { + char *p; + ADDRESS *a; + + a = parseaddr(q->q_paddr, NULLADDR, RF_COPYALL, '\0', NULL, e, + true); + if (a == NULL) + p = ""; + else + p = a->q_user; + hfunc = 0; + while (*p != '\0') + { + int c = *p++; + + if (isascii(c) && isupper(c)) + c = tolower(c); + hfunc = ((hfunc << 1) ^ c) % HASH_SIZE; + } + q->q_nhash = addrhash[hfunc]; + addrhash[hfunc] = q; + } + chainlast = pq; + } + + void + clear_rcpt_hash() + { + int i; + + if (--use_hash > 0) + return; + + for (i = 0; i < HASH_SIZE; i++) + addrhash[i] = NULL; + } + #endif + /* ** SORTHOST -- strcmp()-like func for host portion of an ADDRESS ** *************** *** 280,285 **** --- 336,344 ---- /* various flag bits */ a->q_flags &= ~QINHERITEDBITS; a->q_flags |= ctladdr->q_flags & QINHERITEDBITS; + #if FORWARDPROGCTL + a->q_flags |= ctladdr->q_flags & QDOTFORWARD; + #endif /* DSN recipient information */ a->q_finalrcpt = ctladdr->q_finalrcpt; *************** *** 463,468 **** --- 522,530 ---- char *buf; char buf0[MAXNAME + 1]; /* unquoted image of the user name */ sortfn_t *sortfn; + #if RCPT_HASH + int hfunc; + #endif p = NULL; quoted = false; *************** *** 655,660 **** --- 717,733 ---- usrerrenh(new->q_status, "550 Cannot mail directly to programs"); } + #if FORWARDPROGCTL + else if (bitset(QDOTFORWARD, new->q_flags) && + wordinclass("@", 'f') && + new->q_alias->q_ruser != NULL && + !wordinclass(new->q_alias->q_ruser, 'f')) + { + new->q_state = QS_BADADDR; + new->q_status = "5.7.1"; + usrerr("550 User %s does not have permission for mailing to programs", new->q_alias->q_ruser); + } + #endif else if (bitset(QBOGUSSHELL, new->q_alias->q_flags)) { new->q_state = QS_BADADDR; *************** *** 708,714 **** --- 781,817 ---- else sortfn = sortbysignature; + #if RCPT_HASH + if (use_hash) + { + /* get hash entry */ + char *p; + register ADDRESS *b; + + b = parseaddr(new->q_paddr, NULLADDR, RF_COPYALL, '\0', NULL, e, + true); + if (b == NULL) + p = ""; + else + p = b->q_user; + hfunc = 0; + while (*p != '\0') + { + int c = *p++; + + if (isascii(c) && isupper(c)) + c = tolower(c); + hfunc = ((hfunc << 1) ^ c) % HASH_SIZE; + } + pq = &addrhash[hfunc]; + } + else + pq = sendq; + + for (; (q = *pq) != NULL; pq = use_hash?(&q->q_nhash):(&q->q_next)) + #else for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next) + #endif { /* ** If address is "less than" it should be inserted now. *************** *** 732,738 **** --- 835,846 ---- ** before saying these are the identical addresses. */ + #if MF_SEPARATE + if (!bitnset(M_SEP, m->m_flags) && + sameaddr(q, new) && + #else if (sameaddr(q, new) && + #endif (bitset(QRCPTOK, q->q_flags) || !bitset(QPRIMARY, q->q_flags))) { *************** *** 778,783 **** --- 886,902 ---- SM_ASSERT(pq != NULL); /* add address on list */ + #if RCPT_HASH + if (use_hash) + { + new->q_nhash = addrhash[hfunc]; + addrhash[hfunc] = new; + *chainlast = new; + chainlast = &new->q_next; + new->q_next = NULL; + } + else + #endif if (insert) { /* *************** *** 1818,1823 **** --- 1937,1945 ---- LineNumber = 0; ctladdr->q_flags &= ~QSELFREF; nincludes = 0; + #if RCPT_HASH + make_rcpt_hash(sendq, e); + #endif while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL && !maxreached) { *************** *** 1853,1859 **** --- 1975,1989 ---- "forward %.200s => %s", oldto, shortenstring(buf, MAXSHORTSTR)); + #if FORWARDPROGCTL + if (forwarding) + ctladdr->q_flags |= QDOTFORWARD; + #endif nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e); + #if FORWARDPROGCTL + if (forwarding) + ctladdr->q_flags &= ~QDOTFORWARD; + #endif if (forwarding && MaxForwardEntries > 0 && *************** *** 1886,1891 **** --- 2016,2024 ---- } } } + #if RCPT_HASH + clear_rcpt_hash(); + #endif (void) sm_io_close(fp, SM_TIME_DEFAULT); FileName = oldfilename; *** sendmail/savemail.c.ORG Wed Nov 29 09:20:41 2006 --- sendmail/savemail.c Wed Aug 1 16:54:28 2007 *************** *** 1294,1301 **** --- 1294,1310 ---- { time_t xdate; + #if MAILER_TIMEOUTS + if (q->q_mailer->m_to_q_return > 0) + xdate = e->e_parent->e_ctime + + q->q_mailer->m_to_q_return; + else + xdate = e->e_parent->e_ctime + + TimeOuts.to_q_return[e->e_parent->e_timeoutclass]; + #else xdate = e->e_parent->e_ctime + TimeOuts.to_q_return[e->e_parent->e_timeoutclass]; + #endif (void) sm_strlcpyn(buf, sizeof(buf), 2, "Will-Retry-Until: ", arpadate(ctime(&xdate))); *** sendmail/sendmail.h.ORG Wed Feb 28 07:21:13 2007 --- sendmail/sendmail.h Wed Aug 1 16:55:07 2007 *************** *** 221,239 **** --- 221,257 ---- ** Addresses are stored internally in this structure. */ + #if MULTI_MAILER + #define q_user q_users[0] + #define q_host q_hosts[0] + #define q_mailer q_mailers[0] + #endif /* MULTI_MAILER */ + struct address { char *q_paddr; /* the printname for the address */ + #if MULTI_MAILER + char *q_users[MAXDSPTMAILERS]; /* user name */ + #else /* MULTI_MAILER */ char *q_user; /* user name */ + #endif /* MULTI_MAILER */ char *q_ruser; /* real user name, or NULL if q_user */ + #if MULTI_MAILER + char *q_hosts[MAXDSPTMAILERS]; /* host name */ + struct mailer *q_mailers[MAXDSPTMAILERS]; /* mailer to use */ + #else /* MULTI_MAILER */ char *q_host; /* host name */ struct mailer *q_mailer; /* mailer to use */ + #endif /* MULTI_MAILER */ unsigned long q_flags; /* status flags, see below */ uid_t q_uid; /* user-id of receiver (if known) */ gid_t q_gid; /* group-id of receiver (if known) */ char *q_home; /* home dir (local mailer only) */ char *q_fullname; /* full name if known */ struct address *q_next; /* chain */ + #if RCPT_HASH + struct address *q_nhash; /* hashed chain */ + #endif struct address *q_alias; /* address this results from */ char *q_owner; /* owner of q_alias */ struct address *q_tchain; /* temporary use chain */ *************** *** 274,279 **** --- 292,300 ---- #define QBYTRACE 0x00008000 /* DeliverBy: trace */ #define QBYNDELAY 0x00010000 /* DeliverBy: notify, delay */ #define QBYNRELAY 0x00020000 /* DeliverBy: notify, relayed */ + #if FORWARDPROGCTL + # define QDOTFORWARD 0x10000000 /* this address is from .forward */ + #endif #define QTHISPASS 0x40000000 /* temp: address set this pass */ #define QRCPTOK 0x80000000 /* recipient() processed address */ *************** *** 409,414 **** --- 430,449 ---- time_t m_wait; /* timeout to wait for end */ int m_maxrcpt; /* max recipients per envelope client-side */ short m_qgrp; /* queue group for this mailer */ + #if MULTI_MAILER + int m_rmin; /* recipient lower limit */ + #endif + #if MAILER_PREF + int m_pref; /* mailer preference */ + ADDRESS *m_addrhead; /* working address pointer (head) */ + ADDRESS *m_addrtail; /* working address pointer (tail) */ + #endif + #if CLIENT_SMTP_CONFIG + struct client_config *m_ccnf; + #endif + #if MAILER_TIMEOUTS + time_t m_to_q_return; /* queue return timeouts */ + #endif }; /* bits for m_flags */ *************** *** 473,478 **** --- 508,526 ---- #define M_HOLD '%' /* Hold delivery until ETRN/-qI/-qR/-qS */ #define M_PLUS '+' /* Reserved: Used in mc for adding new flags */ #define M_MINUS '-' /* Reserved: Used in mc for removing flags */ + #if MULTI_MAILER + # define M_DIRECTONLY '!' /* do not use for run-queuing */ + # define M_NONEXT '_' /* do not try next mailer */ + #endif + #if MAILER_PREF + # define M_SORT '<' /* sort recipient list by domain name */ + #endif + #if SPR_CON_CACHE + # define M_NOCACHE ';' /* suppress connection caching on this mailer */ + #endif + #if MF_SEPARATE + # define M_SEP '^' /* do not supress duplicates */ + #endif /* functions */ extern void initerrmailers __P((void)); *************** *** 862,867 **** --- 910,918 ---- HDR *e_header; /* head of header list */ long e_msgpriority; /* adjusted priority of this message */ time_t e_ctime; /* time message appeared in the queue */ + #if 1 /* start time of sendmail to pass to SMTPfeed for statistics */ + time_t e_stime; /* time processing started */ + #endif char *e_to; /* (list of) target person(s) */ ADDRESS e_from; /* the person it is from */ char *e_sender; /* e_from.q_paddr w comments stripped */ *************** *** 1970,1975 **** --- 2021,2029 ---- EXTERN QUEUE_CHAR *QueueLimitRecipient; /* limit queue run to rcpt */ EXTERN QUEUE_CHAR *QueueLimitSender; /* limit queue run to sender */ EXTERN QUEUEGRP *Queue[MAXQUEUEGROUPS + 1]; /* queue groups */ + #if CTE8CHECK + EXTERN char *CTE8BitCheck; /* incorrect CTE: 8bit check */ + #endif /* functions */ extern void assign_queueid __P((ENVELOPE *)); *************** *** 2636,2641 **** --- 2690,2703 ---- extern int xunlink __P((char *)); extern char *xuntextify __P((char *)); + #if CLIENT_SMTP_CONFIG + struct client_config + { + char *heloname; + SOCKADDR addr; + struct client_config *next; + }; + #endif #undef EXTERN #endif /* ! _SENDMAIL_H */ *** sendmail/usersmtp.c.ORG Thu Dec 14 05:11:15 2006 --- sendmail/usersmtp.c Wed Aug 1 16:28:43 2007 *************** *** 74,79 **** --- 74,82 ---- register char *p; register char *hn; char *enhsc; + #if CLIENT_SMTP_CONFIG + char adrbuf[32], *myheloname; + #endif enhsc = NULL; if (tTd(18, 1)) *************** *** 151,156 **** --- 154,237 ---- */ helo: + #if CLIENT_SMTP_CONFIG + myheloname = NULL; + if (m->m_ccnf == NULL) + myheloname = MyHostName; + else + { + SOCKADDR sa; + int len = sizeof(SOCKADDR); + int s = sm_io_getinfo(mci->mci_out, SM_IO_WHAT_FD, NULL); + + if (getsockname(s, (struct sockaddr*)&sa, &len) >= 0) + { + struct hostent *hp; + struct client_config *ccnf; + + ccnf = m->m_ccnf; + while (ccnf != NULL) + { + if (ccnf->addr.sa.sa_family == sa.sa.sa_family) + break; + ccnf = ccnf->next; + } + if (ccnf == NULL || ccnf->heloname == NULL) + { + myheloname = MyHostName; + goto skip_resolv; + } + if (strcmp(ccnf->heloname, "@") != 0) + { + myheloname = ccnf->heloname; + goto skip_resolv; + } + + switch (sa.sa.sa_family) + { + case AF_INET: + hp = sm_gethostbyaddr((char *) &sa.sin.sin_addr.s_addr, INADDRSZ, AF_INET); + if (hp != NULL) + { + myheloname = hp->h_name; + while (strchr(myheloname, '.') == NULL && hp->h_aliases != NULL && *hp->h_aliases != NULL) + { + if (strchr(*hp->h_aliases, '.') != NULL) + myheloname = *hp->h_aliases; + hp->h_aliases++; + } + } + break; + #if NETINET6 + case AF_INET6: + hp = sm_gethostbyaddr((char *) &sa.sin6.sin6_addr, IN6ADDRSZ, AF_INET6); + if (hp != NULL) + { + myheloname = hp->h_name; + while (strchr(myheloname, '.') == NULL && hp->h_aliases != NULL && *hp->h_aliases != NULL) + { + if (strchr(*hp->h_aliases, '.') != NULL) + myheloname = *hp->h_aliases; + hp->h_aliases++; + } + } + break; + #endif + } + + if (myheloname == NULL && sa.sa.sa_family != 0) + { + sm_snprintf(adrbuf, sizeof(adrbuf), "[%s]", + anynet_ntoa(&sa)); + myheloname = adrbuf; + } + } + } + skip_resolv: + if (myheloname == NULL) + myheloname = MyHostName; + #endif + if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags)) mci->mci_flags |= MCIF_ESMTP; hn = mci->mci_heloname ? mci->mci_heloname : MyHostName; *************** *** 161,178 **** --- 242,271 ---- #endif /* _FFR_IGNORE_EXT_ON_HELO */ if (bitnset(M_LMTP, m->m_flags)) { + #if CLIENT_SMTP_CONFIG + smtpmessage("LHLO %s", m, mci, myheloname); + #else smtpmessage("LHLO %s", m, mci, hn); + #endif SmtpPhase = mci->mci_phase = "client LHLO"; } else if (bitset(MCIF_ESMTP, mci->mci_flags) && !bitnset(M_FSMTP, m->m_flags)) { + #if CLIENT_SMTP_CONFIG + smtpmessage("EHLO %s", m, mci, myheloname); + #else smtpmessage("EHLO %s", m, mci, hn); + #endif SmtpPhase = mci->mci_phase = "client EHLO"; } else { + #if CLIENT_SMTP_CONFIG + smtpmessage("HELO %s", m, mci, myheloname); + #else smtpmessage("HELO %s", m, mci, hn); + #endif SmtpPhase = mci->mci_phase = "client HELO"; #if _FFR_IGNORE_EXT_ON_HELO mci->mci_flags |= MCIF_HELO; *** sendmail/version.c.ORG Wed Apr 4 06:21:18 2007 --- sendmail/version.c Wed Aug 1 16:55:35 2007 *************** *** 15,18 **** SM_RCSID("@(#)$Id: version.c,v 8.191 2007/04/03 21:21:18 ca Exp $") ! char Version[] = "8.14.1"; --- 15,18 ---- SM_RCSID("@(#)$Id: version.c,v 8.191 2007/04/03 21:21:18 ca Exp $") ! char Version[] = "8.14.1+3.5Wbeta";