diff options
-rw-r--r-- | AUTHORS | 0 | ||||
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | INSTALL | 182 | ||||
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 0 | ||||
-rw-r--r-- | README.mutt | 27 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rwxr-xr-x | autogen.sh | 9 | ||||
-rw-r--r-- | configure.ac | 29 | ||||
-rw-r--r-- | esmtp.1 | 418 | ||||
-rw-r--r-- | lexer.l | 129 | ||||
-rw-r--r-- | main.c | 482 | ||||
-rw-r--r-- | parser.y | 116 | ||||
-rw-r--r-- | sample.esmtprc | 15 |
15 files changed, 1758 insertions, 0 deletions
@@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..fea1c39 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,9 @@ +bin_PROGRAMS = esmtp + +man_MANS = esmtp.1 + +esmtp_SOURCES = main.c parser.y lexer.l + +EXTRA_DIST = README.mutt sample.esmtprc + +AM_YFLAGS = -d diff --git a/README.mutt b/README.mutt new file mode 100644 index 0000000..9881d83 --- /dev/null +++ b/README.mutt @@ -0,0 +1,27 @@ +To use esmtp with mutt add + + set sendmail="/path/to/esmtp" + +to your ~/.muttrc and create a ~/.esmtp (see sample.esmtp for an example.) + + +For debugging purposes you may prefer using the follwing shell script. + + #!/bin/sh + + LOGFILE=/tmp/esmtp.log + + echo $0 $@ > $LOGFILE + + /path/to/esmtp -m $@ >> $LOGFILE + + exit $? + +Save it as esmtp.sh and put in you ~/.muttrc + + set sendmail="/path/to/esmtp.sh" + +instead. + + +TODO: This would be better handled if done by esmtp itself and controllable by a configuration setting. @@ -0,0 +1,2 @@ +- handle the '-t' option +- better handling of other sendmail options diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..de1db69 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,9 @@ +#! /bin/sh + +export WANT_AUTOMAKE_1_6=1 + +aclocal \ +&& automake --gnu --add-missing \ +&& autoconf \ +&& ./configure --enable-maintainer-mode + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..4a01f27 --- /dev/null +++ b/configure.ac @@ -0,0 +1,29 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(Makefile.am) +AM_INIT_AUTOMAKE(esmtp, 0.1) + +AM_MAINTAINER_MODE + +AC_PROG_CC +AC_PROG_CPP + +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h unistd.h) + +dnl getopt needs this +AC_C_CONST + +AM_PROG_LEX +AC_PROG_MAKE_SET +AC_PROG_YACC + +YFLAGS=-d + +dnl Check for libESMTP +AC_CHECK_LIB(esmtp, smtp_start_session, + LIBS="$LIBS -lesmtp -lpthread", + AC_MSG_ERROR([*** libESMTP library not found.]), + -lpthread) + +AC_OUTPUT([Makefile]) @@ -0,0 +1,418 @@ +.\" Based on ssmtp.1 and sendmail.8 man pages of the sSMTP and +.\" sendmail distributions respectively. +.\" +.\" Portions are +.\" Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1983, 1997 Eric P. Allman. All rights reserved. +.\" Copyright (c) 1988, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.TH ESMTP 1 +.SH NAME +esmtp +.SH SUMMARY +libESMTP to Sendmail compatibility interface +.SH SYNOPSIS +.B esmtp +.RI "[ " flags " ] [ " address " " ... " ]" +.br +.SH DESCRIPTION +.B Esmtp +is a send-only +.B sendmail +emulator for machines which normally retrieve their mail +up from a centralized mailhub +using programs such as +.B fetchmail +. +.PP +.B Esmtp +does not attempt to provide all the functionality of +.B sendmail +: it is intended to be used by other +mail user agents as +.B mutt +. + +.SH OPTIONS +Most +.B sendmail +options are irrelevent to +.B esmtp +. Those marked ``ignored'' or +``default'' have no effect on mail transfer. Those marked ``unsupported'' +are fatal errors. Those marked ``simulated'' are not errors, but the result +is for the program to exit with an informative message. A sort of fatal +non-error. + +.TP +.B \-Ac +(ignored) +Use submit.cf even if the operation mode does not indicate +an initial mail submission. + +.TP +.B \-Am +(ignored) +Use sendmail.cf even if the operation mode indicates +an initial mail submission. + +.TP +.BI \-B type +(ignored) +Set the body type to +.IR type . +Current legal values are +7BIT +or +8BITMIME. + +.TP +.B \-ba +(ignored) +Go into +ARPANET +mode. All input lines must end with a CR-LF, +and all messages will be generated with a CR-LF at the end. +Also, +the ``From:'' and ``Sender:'' +fields are examined for the name of the sender. + +.TP +.B \-bd +(ignored) +Run as a daemon. + +.TP +.B \-bD +(ignored) +Same as +.B \-bd +except runs in foreground. + +.TP +.B \-bh +(ignored) +Print the persistent host status database. + +.TP +.B \-bH +(ignored) +Purge expired entries from the persistent host status database. + +.TP +.B \-bi +(ignored) +Initialize the alias database. + +.TP +.B \-bm +(ignored) +Deliver mail in the usual way (default). + +.TP +.B \-bp +(ignored) +Print a listing of the queue(s). + +.TP +.B \-bP +(ignored) +Print number of entries in the queue(s); +only available with shared memory support. + +.TP +.B \-bs +(ignored) +Use the +SMTP +protocol as described in +RFC821 +on standard input and output. +This flag implies all the operations of the +.B \-ba +flag that are compatible with +SMTP. + +.TP +.B \-bt +(ignored) +Run in address test mode. + +.TP +.B \-bv +(ignored) +Verify names only \- do not try to collect or deliver a message. + +.TP +.BI \-C file +(ignored) +Use alternate configuration file. + +.TP +.BI \-d X +(ignored) +Set debugging value to +.IR X . +.ne 1i + +.TP +.BI \-F fullname +Set the full name of the sender. + +.TP +.BI \-f name +Sets the name of the ``from'' person +(i.e., the envelope sender of the mail). +This address may also be used in the From: header +if that header is missing during initial submission. +The envelope sender address is used as the recipient +for delivery status notifications +and may also appear in a Return-Path: header. +.B \-f +should only be used +by ``trusted'' users +(normally +.IR root ", " daemon , +and +.IR network ) +or if the person you are trying to become +is the same as the person you are. +Otherwise, +an X-Authentication-Warning header +will be added to the message. + +.TP +.BI \-G +(ignored) +Relay (gateway) submission of a message, +e.g., when +.BR rmail +calls +.B sendmail . + +.TP +.BI \-h N +(ignored) +Set the hop count to +.IR N . +The hop count is incremented every time the mail is +processed. +When it reaches a limit, +the mail is returned with an error message, +the victim of an aliasing loop. +If not specified, +``Received:'' lines in the message are counted. + +.TP +.B \-i +(ignored) +Ignore dots alone on lines by themselves in incoming messages. +This should be set if you are reading data from a file. + +.TP +.BI "\-L " tag +(ignored) +Set the identifier used in syslog messages to the supplied +.IR tag . + +.TP +.BI "\-N " dsn +Set delivery status notification conditions to +.IR dsn , +which can be +`never' +for no notifications +or a comma separated list of the values +`failure' +to be notified if delivery failed, +`delay' +to be notified if delivery is delayed, and +`success' +to be notified when the message is successfully delivered. + +.TP +.B \-n +(ignored) +Don't do aliasing. + +.TP +\fB\-O\fP \fIoption\fR=\fIvalue\fR +(ignored) +Set option +.I option +to the specified +.IR value . +This form uses long names. See below for more details. + +.TP +.BI \-o "x value" +(ignored) +Set option +.I x +to the specified +.IR value . +This form uses single character names only. +The short names are not described in this manual page; +see the +.I "Sendmail Installation and Operation Guide" +for details. + +.TP +.BI \-p protocol +(ignored) +Set the name of the protocol used to receive the message. +This can be a simple protocol name such as ``UUCP'' +or a protocol and hostname, such as ``UUCP:ucbvax''. + +.TP +\fB\-q\fR[\fItime\fR] +(ignored) +Process saved messages in the queue at given intervals. +If +.I time +is omitted, process the queue once. +.I Time +is given as a tagged number, +with +`s' +being seconds, +`m' +being minutes (default), +`h' +being hours, +`d' +being days, +and +`w' +being weeks. +For example, +`\-q1h30m' +or +`\-q90m' +would both set the timeout to one hour thirty minutes. +By default, +.B sendmail +will run in the background. +This option can be used safely with +.BR \-bd . + +.TP +\fB\-qp\fR[\fItime\fR] +(ignored) +Similar to \fB\-q\fItime\fR, +except that instead of periodically forking a child to process the queue, +sendmail forks a single persistent child for each queue +that alternates between processing the queue and sleeping. +The sleep time is given as the argument; it defaults to 1 second. +The process will always sleep at least 5 seconds if the queue was +empty in the previous queue run. + +.TP +\fB\-q\fRf +(ignored) +Process saved messages in the queue once and do not fork(), +but run in the foreground. + +.TP +\fB\-q\fRG name +(ignored) +Process jobs in queue group called +.I name +only. + +.TP +\fB\-q\fR[\fI!\fR]I substr +(ignored) +Limit processed jobs to those containing +.I substr +as a substring of the queue id or not when +.I ! +is specified. + +.TP +\fB\-q\fR[\fI!\fR]R substr +(ignored) +Limit processed jobs to those containing +.I substr +as a substring of one of the recipients or not when +.I ! +is specified. + +.TP +\fB\-q\fR[\fI!\fR]S substr +(ignored) +Limit processed jobs to those containing +.I substr +as a substring of the sender or not when +.I ! +is specified. + +.TP +.BI "\-R " return +(ignored) +Set the amount of the message to be returned +if the message bounces. +The +.I return +parameter can be +`full' +to return the entire message or +`hdrs' +to return only the headers. +In the latter case also local bounces return only the headers. + +.TP +.BI \-r name +An alternate and obsolete form of the +.B \-f +flag. + +.TP +.B \-t +(unsupported) +Read message for recipients. +To:, Cc:, and Bcc: lines will be scanned for recipient addresses. +The Bcc: line will be deleted before transmission. + +.TP +.BI "\-V " envid +(ignored) +Set the original envelope id. +This is propagated across SMTP to servers that support DSNs +and is returned in DSN-compliant error messages. + +.TP +.B \-v +Go into verbose mode. +Alias expansions will be announced, etc. + +.TP +.BI "\-X " logfile +(ignored) +Log all traffic in and out of mailers in the indicated log file. +This should only be used as a last resort +for debugging mailer bugs. +It will log a lot of data very quickly. + +.TP +.B \-\- +Stop processing command flags and use the rest of the arguments as +addresses. +.SH FILES +.TP + ~/.esmtp +configuration file + +.SH SEE ALSO +fetchmail(1) + +.SH DIAGNOSTICS + +.SH AUTHORS +José Fonseca (j_r_fonseca@yahoo.co.uk) +Brian Stafford (brian@stafford.uklinux.net) + +.SH BUGS +.B esmtp +ignores most of sendmail options. @@ -0,0 +1,129 @@ +%{ +/* + * lexer.l -- lexer for the rcfile + */ + +/* + * Adapted from fetchmail's rcfile_l.l by José Fonseca + */ + +#include <stdio.h> +#include <string.h> + +#include "parser.h" + +#define MSGBUFSIZE 8192 + +int lineno = 1; + +void escapes(const char *tp, char *cp); + +%} + +%s NAME + +%% + +\"[^\"]*\" { + char buf[MSGBUFSIZE]; + + yytext[strlen(yytext)-1] = '\0'; + escapes(yytext+1, buf); + yylval.sval = (char *) strdup(buf); + BEGIN(0); + return STRING; + } +\'[^\']*\' { + char buf[MSGBUFSIZE]; + + yytext[strlen(yytext)-1] = '\0'; + escapes(yytext+1, buf); + yylval.sval = (char *) strdup(buf); + BEGIN(0); + return STRING; + } + +<NAME>[^=;, \t\r\n]+ { + char buf[MSGBUFSIZE]; + + escapes(yytext, buf); + yylval.sval = (char *) strdup(buf); + BEGIN(0); + return STRING; + } + + + +host(name)? { BEGIN(NAME); return HOSTNAME; } +user(name)? { BEGIN(NAME); return USERNAME; } +pass(word)? { BEGIN(NAME); return PASSWORD; } +(start)?tls { return STARTTLS; } +(certificate_)?passphrase { return CERTIFICATE_PASSPHRASE; } + += { return MAP; } + +disabled { return DISABLED; } +enabled { return ENABLED; } +required { return REQUIRED; } + +(#.*)?\\?\n { lineno++; } /* newline is ignored */ + +-?[0-9]+/[^a-zA-Z] { yylval.number = atoi(yytext); return NUMBER; } + +[^=;:, \t\r\n]+ { + char buf[MSGBUFSIZE]; + + escapes(yytext, buf); + yylval.sval = (char *) strdup(buf); + return STRING; + } + +[ \t\r]+ ; /* whitespace */ + +%% + +void escapes(cp, tp) +/* process standard C-style escape sequences in a string */ +const char *cp; /* source string with escapes */ +char *tp; /* target buffer for digested string */ +{ + while (*cp) + { + int cval = 0; + + if (*cp == '\\' && strchr("0123456789xX", cp[1])) + { + char *dp; + const char *hex = "00112233445566778899aAbBcCdDeEfF"; + int dcount = 0; + + if (*++cp == 'x' || *cp == 'X') + for (++cp; (dp = strchr(hex, *cp)) && (dcount++ < 2); cp++) + cval = (cval * 16) + (dp - hex) / 2; + else if (*cp == '0') + while (strchr("01234567",*cp) != (char*)NULL && (dcount++ < 3)) + cval = (cval * 8) + (*cp++ - '0'); + else + while ((strchr("0123456789",*cp)!=(char*)NULL)&&(dcount++ < 3)) + cval = (cval * 10) + (*cp++ - '0'); + } + else if (*cp == '\\') /* C-style character escapes */ + { + switch (*++cp) + { + case '\\': cval = '\\'; break; + case 'n': cval = '\n'; break; + case 't': cval = '\t'; break; + case 'b': cval = '\b'; break; + case 'r': cval = '\r'; break; + default: cval = *cp; + } + cp++; + } + else + cval = *cp++; + *tp++ = cval; + } + *tp = '\0'; +} + @@ -0,0 +1,482 @@ +/* + * A libESMTP Example Application. + * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This program attemps to mimic the sendmail program behavior using libESMTP. + * + * Adapted from the libESMTP's mail-file example by José Fonseca. + */ +#define _XOPEN_SOURCE 500 + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <unistd.h> +#include <getopt.h> +#include <string.h> +#include <fcntl.h> +#include <signal.h> +#include <errno.h> + +#include <auth-client.h> +#include <libesmtp.h> + +char *from = NULL; +char *host = NULL; +char *user = NULL; +char *pass = NULL; +enum starttls_option starttls = Starttls_DISABLED; +char *certificate_passphrase = NULL; + +extern void parse_rcfile(void); + +/* Callback function to read the message from a file. Since libESMTP + does not provide callbacks which translate line endings, one must + be provided by the application. + + The message is read a line at a time and the newlines converted + to \r\n. Unfortunately, RFC 822 states that bare \n and \r are + acceptable in messages and that individually they do not constitute a + line termination. This requirement cannot be reconciled with storing + messages with Unix line terminations. RFC 2822 rescues this situation + slightly by prohibiting lone \r and \n in messages. + + The following code cannot therefore work correctly in all situations. + Furthermore it is very inefficient since it must search for the \n. + */ +#define BUFLEN 8192 + +const char * +readlinefp_cb (void **buf, int *len, void *arg) +{ + int octets; + + if (*buf == NULL) + *buf = malloc (BUFLEN); + + if (len == NULL) + { + rewind ((FILE *) arg); + return NULL; + } + + if (fgets (*buf, BUFLEN - 2, (FILE *) arg) == NULL) + octets = 0; + else + { + char *p = strchr (*buf, '\0'); + + if (p[-1] == '\n' && p[-2] != '\r') + { + strcpy (p - 1, "\r\n"); + p++; + } + octets = p - (char *) *buf; + } + *len = octets; + return *buf; +} + +void +monitor_cb (const char *buf, int buflen, int writing, void *arg) +{ + FILE *fp = arg; + + if (writing == SMTP_CB_HEADERS) + { + fputs ("H: ", fp); + fwrite (buf, 1, buflen, fp); + return; + } + + fputs (writing ? "C: " : "S: ", fp); + fwrite (buf, 1, buflen, fp); + if (buf[buflen - 1] != '\n') + putc ('\n', fp); +} + +void +usage (void) +{ + fputs ("usage: esmtp [options] mailbox [mailbox ...]\n", + stderr); +} + +void +version (void) +{ + char buf[32]; + + smtp_version (buf, sizeof buf, 0); + printf ("libESMTP version %s\n", buf); +} + +/* Callback to request user/password info. Not thread safe. */ +int +authinteract (auth_client_request_t request, char **result, int fields, + void *arg) +{ + int i; + + for (i = 0; i < fields; i++) + { + if (request[i].flags & AUTH_USER && user) + result[i] = user; + else if (request[i].flags & AUTH_PASS && pass) + result[i] = pass; + else + return 0; + } + return 1; +} + +int +tlsinteract (char *buf, int buflen, int rwflag, void *arg) +{ + char *pw; + int len; + + if (certificate_passphrase) + { + pw = certificate_passphrase; + len = strlen (pw); + if (len + 1 > buflen) + return 0; + strcpy (buf, pw); + return len; + } + else + return 0; +} + +/* Callback to print the recipient status */ +void +print_recipient_status (smtp_recipient_t recipient, + const char *mailbox, void *arg) +{ + const smtp_status_t *status; + + status = smtp_recipient_status (recipient); + fprintf (stderr, "%s: %d %s\n", mailbox, status->code, status->text); +} + +int +main (int argc, char **argv) +{ + smtp_session_t session; + smtp_message_t message; + smtp_recipient_t recipient; + auth_context_t authctx; + const smtp_status_t *status; + struct sigaction sa; + int c; + int ret; + enum notify_flags notify = Notify_NOTSET; + + /* Parse the rc file. */ + parse_rcfile(); + + /* This program sends only one message at a time. Create an SMTP + session and add a message to it. */ + auth_client_init (); + session = smtp_create_session (); + message = smtp_add_message (session); + + while ((c = getopt (argc, argv, + "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:")) != EOF) + switch (c) + { + case 'A': + /* Use alternate sendmail/submit.cf */ + break; + + case 'B': + /* Body type */ + break; + + case 'C': + /* Select configuration file */ + break; + + case 'F': + /* Set full name */ + break; + + case 'G': + /* Relay (gateway) submission */ + break; + + case 'I': + /* Initialize alias database */ + break; + + case 'L': + /* Program label */ + break; + + case 'M': + /* Define macro */ + break; + + case 'N': + /* Delivery status notifications */ + if (strcmp (optarg, "never") == 0) + notify = Notify_NEVER; + else + { + if (strstr (optarg, "failure")) + notify |= Notify_FAILURE; + if (strstr (optarg, "delay")) + notify |= Notify_DELAY; + if (strstr (optarg, "success")) + notify |= Notify_SUCCESS; + } + break; + + case 'R': + /* What to return */ + break; + + case 'T': + /* Set timeout interval */ + break; + + case 'X': + /* Traffic log file */ + break; + + case 'V': + /* Set original envelope id */ + break; + + case 'b': + /* Operations mode */ + break; + + case 'c': + /* Connect to non-local mailers */ + break; + + case 'd': + /* Debugging */ + break; + + case 'e': + /* Error message disposition */ + break; + + case 'f': + /* From address */ + case 'r': + /* Obsolete -f flag */ + from = optarg; + break; + + case 'h': + /* Hop count */ + break; + + case 'i': + /* Don't let dot stop me */ + break; + + case 'm': + /* Send to me too */ + break; + + case 'n': + /* don't alias */ + break; + + case 'o': + /* Set option */ + break; + + case 'p': + /* Set protocol */ + break; + + case 'q': + /* Run queue files at intervals */ + if (optarg[0] == '!') + { + /* Negate the meaning of pattern match */ + optarg++; + } + + switch (optarg[0]) + { + case 'G': + /* Limit by queue group name */ + break; + + case 'I': + /* Limit by ID */ + break; + + case 'R': + /* Limit by recipient */ + break; + + case 'S': + /* Limit by sender */ + break; + + case 'f': + /* Forground queue run */ + break; + + case 'p': + /* Persistent queue */ + if (optarg[1] == '\0') + break; + ++optarg; + + default: + break; + } + break; + + case 's': + /* Save From lines in headers */ + break; + + case 't': + /* Read recipients from message */ + fprintf (stderr, "Unsupported option 't'\n"); + exit (2); + break; + + case 'v': + /* Verbose */ + smtp_set_monitorcb (session, monitor_cb, stdout, 1); + break; + + default: + usage (); + exit (2); + } + + /* At least one more argument is needed. + */ + if (optind > argc - 1) + { + usage (); + exit (2); + } + + /* NB. libESMTP sets timeouts as it progresses through the protocol. + In addition the remote server might close its socket on a timeout. + Consequently libESMTP may sometimes try to write to a socket with + no reader. Ignore SIGPIPE, then the program doesn't get killed + if/when this happens. */ + sa.sa_handler = SIG_IGN; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGPIPE, &sa, NULL); + + /* Set the SMTP Starttls extension. */ + smtp_starttls_enable (session, starttls); + + /* Set the host running the SMTP server. LibESMTP has a default port + number of 587, however this is not widely deployed so the port + is specified as 25 along with the default MTA host. */ + smtp_set_server (session, host ? host : "localhost:25"); + + /* Do what's needed at application level to use authentication. + */ + authctx = auth_create_context (); + auth_set_mechanism_flags (authctx, AUTH_PLUGIN_PLAIN, 0); + auth_set_interact_cb (authctx, authinteract, NULL); + + /* Use our callback for X.509 certificate passwords. If STARTTLS is + not in use or disabled in configure, the following is harmless. */ + smtp_starttls_set_password_cb (tlsinteract, NULL); + + /* Now tell libESMTP it can use the SMTP AUTH extension. + */ + smtp_auth_set_context (session, authctx); + + /* Set the reverse path for the mail envelope. (NULL is ok) + */ + smtp_set_reverse_path (message, from); + + /* Open the message file and set the callback to read it. + */ +#if 0 + smtp_set_message_fp (message, stdin); +#else + smtp_set_messagecb (message, readlinefp_cb, stdin); +#endif + + /* At present it can't handle one recipient only out of many + failing. Make libESMTP require all specified recipients to + succeed before transferring a message. */ + smtp_option_require_all_recipients (session, 1); + + /* Add remaining program arguments as message recipients. + */ + while (optind < argc) + { + recipient = smtp_add_recipient (message, argv[optind++]); + + /* Recipient options set here */ + if (notify != Notify_NOTSET) + smtp_dsn_set_notify (recipient, notify); + } + + /* Initiate a connection to the SMTP server and transfer the + message. */ + if (!smtp_start_session (session)) + { + char buf[128]; + + fprintf (stderr, "SMTP server problem %s\n", + smtp_strerror (smtp_errno (), buf, sizeof buf)); + + ret = 1; + } + else + { + /* Report on the success or otherwise of the mail transfer. + */ + status = smtp_message_transfer_status (message); + if (status->code / 100 == 2) + { + ret = 0; + } + else + { + /* Report on the failure of the mail transfer. + */ + status = smtp_message_transfer_status (message); + fprintf (stderr, "%d %s\n", status->code, status->text); + smtp_enumerate_recipients (message, print_recipient_status, NULL); + + ret = 1; + } + } + + /* Free resources consumed by the program. + */ + smtp_destroy_session (session); + auth_destroy_context (authctx); + auth_client_exit (); + exit (ret); +} + diff --git a/parser.y b/parser.y new file mode 100644 index 0000000..5426675 --- /dev/null +++ b/parser.y @@ -0,0 +1,116 @@ +%{ +/* + * parser.y -- parser for the rcfile + */ + +/* + * Adapted from fetchmail's rcfile_y.y by José Fonseca + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libesmtp.h> + +/* parser reads these */ +char *rcfile = NULL; /* path name of dot file */ + +/* parser sets these */ +int yydebug; /* in case we didn't generate with -- debug */ + +extern char *host; +extern char *user; +extern char *pass; +extern enum starttls_option starttls; +extern char *certificate_passphrase; + +/* using Bison, this arranges that yydebug messages will show actual tokens */ +extern char * yytext; +#define YYPRINT(fp, type, val) fprintf(fp, " = \"%s\"", yytext) +%} + +%union { + int number; + char *sval; +} + +%token HOSTNAME USERNAME PASSWORD STARTTLS CERTIFICATE_PASSPHRASE + +%token MAP + +%token DISABLED ENABLED REQUIRED +%token <sval> STRING +%token <number> NUMBER + +%% + +rcfile : /* empty */ + | statement_list + ; + +statement_list : statement + | statement_list statement + ; + +/* future global options should also have the form SET <name> optmap <value> */ +statement : HOSTNAME MAP STRING { host = strdup($3); } + | USERNAME MAP STRING { user = strdup($3); } + | PASSWORD MAP STRING { pass = strdup($3); } + | STARTTLS MAP DISABLED { starttls = Starttls_DISABLED; } + | STARTTLS MAP ENABLED { starttls = Starttls_ENABLED; } + | STARTTLS MAP REQUIRED { starttls = Starttls_REQUIRED; } + | CERTIFICATE_PASSPHRASE MAP STRING { certificate_passphrase = strdup($3); } + ; + +%% + +/* lexer interface */ +extern char *rcfile; +extern int lineno; +extern char *yytext; +extern FILE *yyin; + +void yyerror (const char *s) +/* report a syntax error */ +{ + fprintf(stderr, "%s:%d: %s at %s\n", rcfile, lineno, s, + (yytext && yytext[0]) ? yytext : "end of input"); +} + +#define RCFILE ".esmtprc" +void parse_rcfile (void) +{ + char *home; + + /* Setup the rcfile name. */ + if (!(home = getenv("HOME"))) + return; + + if (!(rcfile = malloc(strlen(home) + sizeof(RCFILE) + 2))) + return; + + strcpy(rcfile, home); + if (rcfile[strlen(rcfile) - 1] != '/') + strcat(rcfile, "/"); + strcat(rcfile, RCFILE); + + /* Open the configuration file and feed it to the lexer. */ + if (!(yyin = fopen(rcfile, "r"))) { + if (errno != ENOENT) { + fprintf(stderr, "open: %s: %s\n", rcfile, strerror(errno)); + } + } + else + { + yyparse(); /* parse entire file */ + + fclose(yyin); /* not checking this should be safe, file mode was r */ + } + + free(rcfile); +} + +/* easier to do this than cope with variations in where the library lives */ +int yywrap(void) { return 1; } diff --git a/sample.esmtprc b/sample.esmtprc new file mode 100644 index 0000000..a5343f2 --- /dev/null +++ b/sample.esmtprc @@ -0,0 +1,15 @@ +#set SMTP host and service (port) +hostname = localhost:25 + +# set the user name +username = "USERNAME" + +# set the password +password = "PASSWORD" + +# use the Starttls +#starttls = { enabled | disabled | required } + +# set the certificate passphrase +#certificate_passphrase = "CERTIFICATE_PASSPHRASE" + |