Imported from ../bash-2.0.tar.gz.
[platform/upstream/bash.git] / examples / scripts.noah / send_mail.bash
1 # send_mail.bash
2 # Author: Noah Friedman <friedman@prep.ai.mit.edu>
3 # Created: 1992-07-02
4 # Public domain
5
6 # Commentary:
7
8 # TODO: implement Fcc headers (see emacs manual)
9
10 # Code:
11
12 #:docstring send_mail:
13 # Usage: send_mail
14 #
15 # This function serves as a simple replacement for sendmail as a client
16 # interface on those systems where it is not available.  It does assume
17 # that one can talk to an SMTP mailer on port 25 either on the local host
18 # or on the host specified by the MAILHOST environment variable.  If you
19 # have access to sendmail, it's better to use 'sendmail -t' instead of this
20 # script (which probably isn't as robust).
21 #
22 # Message is read from stdin, and headers are parsed to determine
23 # recipients.  
24 #:end docstring:
25
26 ###;;;autoload
27 function send_mail ()
28 {
29     # Need gawk, since several extensions are taken advantage of (like
30     # IGNORECASE for regexps).
31     local awk="${GAWK_LOCATION:-gawk}"
32     local DefaultFrom="${USER:-${LOGNAME}}"
33     local From
34     local To
35     local Cc
36     local Bcc
37     local tmpfile="/tmp/send_mail$$"
38
39     while [ -e "${tmpfile}" ]; do
40        tmpfile="/tmp/send_mail${RANDOM}"
41     done
42
43     # Lines consisting only of dots need one more dot appended.  SMTP
44     # servers eat one of the dots (and if only 1 dot appears, it signifies
45     # the end of the message).
46     sed '/^\.\.*/s/^\(\.\.*\)$/\1./' > "${tmpfile}"
47
48     # Parse mail headers in message to extract recipients list. 
49     # This doesn't affect what the user sees---it's only used to generate
50     # the rcpt-to lines for SMTP. 
51     eval $(${awk} -f - "${tmpfile}" <<- '__EOF__'
52        # Try to extract email address from amidst random data
53        function parse_address (data)
54        {
55            # From: "real name" <foobar@host>
56            # From: "" <foobar@host>
57            if (match(data, /^\"[^\"]*\"[ \t]*<.*>/)) {
58               data_idx = match(data, /^\"[^\"]*\"[ \t]*</)
59               data = substr(data, RSTART + RLENGTH);
60               if (data_idx = match(data, ">.*"))
61                  data = substr(data, 1, RSTART - 1);
62               return data
63            }
64            # From: real name <foobar@host>
65            if (match(data, /<.*>/)) {
66               data_idx = match(data, /</)
67               data = substr(data, RSTART + RLENGTH);
68               if (data_idx = match(data, ">"))
69                  data = substr(data, 1, RSTART - 1);
70               return data
71            }
72            # From: foobar@host (real name)
73            if (match(data, /\(.*\)/)) {
74               data_idx = match(data, /\(/);
75               data = substr(data, 1, RSTART - 1);
76               return data
77            }
78            # (hopefully) From: foobar@host
79            return data
80        }
81
82        BEGIN { IGNORECASE = 1; }
83
84        # Blank line signifies end of headers, so we can stop looking.
85        /^$/ { exit(0) }
86
87        /^from:|^to:|^cc:|^bcc:/ {
88           header_idx = match($0, /^[^:]*:/)
89           if (header_idx) {
90              # Capitalize header name
91              header_firstchar = toupper(substr($0, RSTART, 1));
92              header_rest = tolower(substr($0, RSTART + 1, RLENGTH - 2));
93              header = header_firstchar header_rest
94
95              $0 = substr($0, RSTART + RLENGTH + 1);
96              addresses = ""
97              # parse addresses
98              while ($0) {
99                 # Strip leading whitespace
100                 if (idx = match($0, /[ \t]*/))
101                    $0 = substr($0, RSTART + RLENGTH);
102
103                 # Find everything up to a nonquoted comma
104                 # FIXME: doesnt handle quoting yet
105                 if (idx = match($0, /,/)) {
106                    data = substr($0, 1, RSTART);
107                    $0 = substr($0, RSTART + 1);
108                 } else {
109                    data = $0
110                    $0 = ""
111                 }
112                 addresses = addresses " " parse_address(data)
113              }
114
115              printf("%s='%s'\n", header, addresses);
116           }
117        }
118         __EOF__)
119
120     # Not sure if an address is *required* after the HELO.. every sendmail
121     # I tried talking to didn't seem to care.  Some sendmails don't care
122     # if there's a HELO at all. 
123     cat <<- __EOF__ | telnet ${MAILHOST:-localhost} 25 > /dev/null 2>&1
124         HELO
125         mail from: ${From:-${DefaultFrom}}
126         $(for name in ${To} ${Cc} ${Bcc} ; do
127              echo "rcpt to: ${name}"
128           done)
129         data
130         $(cat "${tmpfile}")
131         .
132         quit
133         __EOF__
134
135     rm -f "${tmpfile}"
136 }
137
138 provide send_mail
139
140 # send_mail.bash ends here