From: Ken Hornstein Date: Thu, 23 Jan 2014 18:35:31 +0000 (-0500) Subject: Merge branch 'mhbuild-always' X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/64e8827c5d5def0325ab7181fe939623c77e807c?hp=05b74a00b3df7d4f9c6b5be089491b753d9d1a64 Merge branch 'mhbuild-always' --- diff --git a/Makefile.am b/Makefile.am index 903a45e2..8d88337a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -65,6 +65,7 @@ TESTS = test/ali/test-ali test/anno/test-anno \ test/install-mh/test-install-mh \ test/locking/test-datalocking test/locking/test-spoollocking \ test/manpages/test-manpages \ + test/mhbuild/test-attach \ test/mhbuild/test-forw test/mhbuild/test-header-encode \ test/mhbuild/test-utf8-body \ test/mhfixmsg/test-mhfixmsg \ diff --git a/docs/README-ATTACHMENTS b/docs/README-ATTACHMENTS index dc04662d..db096d66 100644 --- a/docs/README-ATTACHMENTS +++ b/docs/README-ATTACHMENTS @@ -1,3 +1,10 @@ +This document describes the previous attach interface. The attach +interface has changes for nmh 1.6 and later. The interface is +documented in send(1), whatnow(1), and mhbuild(1). No configuration +is required, and the same commands exist in whatnow; the two main +differences are that the header is now named "Attach", and mhbuild takes +care of the actual header processing. + Jon Steinhart's (jon@fourwinds.com) Attachment Handling Mods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/pending-release-notes b/docs/pending-release-notes index 288b5674..b2d2a82a 100644 --- a/docs/pending-release-notes +++ b/docs/pending-release-notes @@ -67,6 +67,11 @@ NEW FEATURES directive that send(1) will use. - mhbuild(1) now supports the -auto/-noauto flags (to be used by send(1) when invoking mhbuild automatically). +- mhbuild(1) now is automatically run by send, to insure that all outgoing + messages have proper MIME formatting. +- A new header, "Attach", is supported by mhbuild; it is used to replace + previous functionality (which by default used a header named + Nmh-Attachment). ----------------- OBSOLETE FEATURES diff --git a/h/mh.h b/h/mh.h index a47b7c20..999d600a 100644 --- a/h/mh.h +++ b/h/mh.h @@ -122,8 +122,6 @@ struct swit { extern struct swit anoyes[]; /* standard yes/no switches */ -#define ATTACHFORMATS 3 /* Number of send attach formats. */ - /* * general folder attributes */ @@ -359,8 +357,6 @@ typedef struct m_getfld_state *m_getfld_state_t; #define LINK "@" /* Name of link to file to which you are */ /* replying. */ -#define NMH_ATTACH_HEADER "Nmh-Attachment" /* Default header for -attach */ - /* * credentials management */ diff --git a/h/mhparse.h b/h/mhparse.h index 62e6c0b3..29fc1afe 100644 --- a/h/mhparse.h +++ b/h/mhparse.h @@ -296,6 +296,9 @@ CT parse_mime (char *); * that the composition file is already in MIME format * and will not be processed further. Otherwise, an * error is generated. + * dist - A flag to indicate if we are being run by "dist". In + * that case, add no MIME headers to the message. Existing + * headers will still be encoded by RFC 2047. * directives - A flag to control whether or not build directives are * processed by default. * encoding - The default encoding to use when doing RFC 2047 header @@ -306,7 +309,8 @@ CT parse_mime (char *); * -auto flag is set and a MIME-Version header is encountered, the return * value is NULL. */ -CT build_mime (char *infile, int autobuild, int directives, int encoding); +CT build_mime (char *infile, int autobuild, int dist, int directives, + int encoding); int add_header (CT, char *, char *); int get_ctinfo (char *, CT, int); diff --git a/h/prototypes.h b/h/prototypes.h index 97f0544e..a8f6d468 100644 --- a/h/prototypes.h +++ b/h/prototypes.h @@ -336,7 +336,7 @@ int sc_length(void); int sc_width(void); int build_form (char *, char *, int *, char *, char *, char *, char *, char *, char *); -int sendsbr (char **, int, char *, char *, struct stat *, int, char *, int); +int sendsbr (char **, int, char *, char *, struct stat *, int); int SOprintf (char *, ...); int what_now (char *, int, int, char *, char *, int, struct msgs *, char *, int, char *, int); diff --git a/man/forw.man b/man/forw.man index 2b73408a..414f9d7d 100644 --- a/man/forw.man +++ b/man/forw.man @@ -275,18 +275,7 @@ composition file. Note that .B nmh will not invoke .B mhbuild -automatically, unless you -add this line to your -.I \&.mh\(ruprofile -file: -.PP -.RS 5 -.nf -automimeproc: 1 -.fi -.RE -.PP -Otherwise, you must specifically give the command +automatically; you must specifically give the command .PP .RS 5 .nf diff --git a/man/mh-profile.man b/man/mh-profile.man index 47c59283..14d1c5ab 100644 --- a/man/mh-profile.man +++ b/man/mh-profile.man @@ -156,16 +156,6 @@ EDITOR environment variables. (profile, default: vi) .RE .PP -.BR automimeproc : -.RS 5 -If defined and set to 1, then the -.B whatnow -program will automatically -invoke the buildmimeproc (discussed below) to process each message as a MIME -composition draft before it is sent. -(profile, no default) -.RE -.PP .BR Msg\-Protect : 600 .RS 5 diff --git a/man/mhbuild.man b/man/mhbuild.man index 9dbf05a8..e4bd7933 100644 --- a/man/mhbuild.man +++ b/man/mhbuild.man @@ -1,4 +1,4 @@ -.TH MHBUILD %manext1% "March 21, 2013" "%nmhversion%" +.TH MHBUILD %manext1% "January 23, 2014" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -21,6 +21,7 @@ mhbuild \- translate MIME composition draft .RB [ \-headerencoding .IR encoding\-algorithm .RB " | " \-autoheaderencoding ] +.RB [ \-dist ] .RB [ \-version ] .RB [ \-help ] .ad @@ -78,6 +79,21 @@ switch is present, then the listing will show any \*(lqextra\*(rq information that is present in the message, such as comments in the \*(lqContent-Type\*(rq header. +.SS "Simplified Attachment Interface" +For users who wish to simply attach files to text content, +.B mhbuild +will scan the composition file for \*(lqAttach\*(rq headers. An +\*(lqAttach\*(rq header contains a filename that will be appended to the +message using normal MIME encapsulation rules. One filename is allowed +per \*(lqAttach\*(rq header, but multiple \*(lqAttach\*(rq headers are +allowed ber composition file. +.PP +These files will be appended after any other MIME content, including any +content specified by +.B mhbuild +directives (see below). See +.IR send (1) +for more details. .SS "Translating the Composition File" .B mhbuild is essentially a filter to aid in the composition of MIME @@ -555,20 +571,11 @@ on file that already in MIME format. The switch will cause .B mhbuild to exit without error if the input file already has valid MIME headers. -.PP -It is also possible to have the -.B whatnow -program invoke -.B mhbuild -automatically when a message is sent. To do this, you must add the line -.PP -.RS 5 -automimeproc: 1 -.RE -.PP -to your -.I \&.mh\(ruprofile -file. +The use of +.B \-auto +also enables the +.B \-nodirectives +switch. .PP Finally, you should consider adding this line to your profile: .PP @@ -587,6 +594,14 @@ What now? list .RE .PP will work as you expect. +.PP +The +.B \-dist +switch is intended to be used by +.BR dist . +It will cause mhbuild to not generate any MIME headers in the composition +file (such as \*(lqMIME-Version\*(rq or \*(lqContent-Type\*(rq), but it +will still encode message headers according to RFC 2047. .SS "User Environment" Because the environment in which .B mhbuild diff --git a/man/repl.man b/man/repl.man index c1cac4bf..245d45ae 100644 --- a/man/repl.man +++ b/man/repl.man @@ -350,16 +350,7 @@ Note that .B nmh will not invoke .B mhbuild -automatically, unless you -add this line to your -.I \&.mh\(ruprofile -file: -.PP -.RS 5 -automimeproc: 1 -.RE -.PP -Otherwise, you must specifically give the command +automatically; you must specifically give the command .PP .RS 5 What now? mime diff --git a/man/send.man b/man/send.man index 83cf19ae..c83a74fe 100644 --- a/man/send.man +++ b/man/send.man @@ -1,7 +1,7 @@ .\" .\" %nmhwarning% .\" -.TH SEND %manext1% "December 22, 2013" "%nmhversion%" +.TH SEND %manext1% "January 23, 2014" "%nmhversion%" .SH NAME send \- send a message .SH SYNOPSIS @@ -54,11 +54,6 @@ send \- send a message \&...] .RB [ \-version ] .RB [ \-help ] -.RB [ \-attach -.IR header-field-name ] -.RB [ \-noattach ] -.RB [ \-attachformat -.IR 0 " | " 1 " | " 2 ] .ad .SH DESCRIPTION .B Send @@ -83,24 +78,39 @@ profile component. Most of the features attributed to are actually performed by .BR post . .PP -By default the draft is scanned for a header named -.IR Nmh-Attachment . +Before +.B send +gives the message to +.B post +for delivery, the message is processed by +.B mhbuild +to perform any necessary MIME encoding of the outgoing message. This +can be changed by the +.I buildmimeproc +profile component. +.B mhbuild +is invoked with the +.B \-auto +switch, so +.B mhbuild +directives are not processed by default. See +.IR mhbuild (1) +for more information. +.PP +.B mhbuild +will scan the message draft for a header named +.IR Attach . The draft is converted to a MIME message if one or more matches are found. -This conversion occurs before all other processing. The header name -can be changed with the -.B \-attach -option. This behavior can be disabled completely with the -.B \-noattach -option. The -.B whatnow +This conversion occurs before all other processing. The +.IR whatnow (1) man page describes the user interface for managing MIME attachments via this mechanism. .PP The first part of the MIME message is the draft body if that body contains any non-blank characters. -The body of each header field whose name matches the -.I header-field-name -is interpreted as a file name, and each file named is included as a separate +The body of each +.I Attach +header field is interpreted as a file name, and each file named is included as a separate part in the MIME message. .PP Determination of the content MIME type inserted into the Content-Type @@ -109,9 +119,9 @@ header for each part depends on how the installation was configured. If a program, such as .B file with a -.B --mime +.B \-\-mime or -.B -i +.B \-i option, was found that can specify the type of a file as a MIME type string, then that will be used. To determine if your .B nmh @@ -135,54 +145,15 @@ if it contains characters outside of the ASCII range. See .IR mhshow (1) for more details and example syntax. .PP -Each part contains a name attribute that is the last component of the path name. -A -.I x-unix-mode -attribute containing the file mode accompanies each part. -Finally, a description attribute is generated by running the -.I file -command on the file. -.PP -The -.B -attachformat -option specifies the MIME header field formats: a value of -.B 0 -includes the -.I x-unix-mode -attribute as noted above. A value of -.BR 1 , -the default, -suppresses that, puts the file name in the -\*(lqContent-Description\*(rq header, and -adds a \*(lqContent-Disposition\*(rq header. A value of -.B 2 -adds the file -.I modification-date -parameter to the \*(lqContent-Disposition\*(rq header. You can -specify one value in your profile, and override it for individual -messages at the -.I whatnow -prompt. -.PP -Here are example message part headers, for an attachment, for each of the -.B -attachformat -values: +Each attached MIME part contains a +\*(lqContent-Description\*(rq header that includes the filename, and +adds a \*(lqContent-Disposition\*(rq header. +Here is an example of MIME part headers for an attachment: .PP .nf --attachformat 0: -Content-Type: text/plain; name="VERSION"; x-unix-mode="0644"; - charset="us-ascii" -Content-Description: ASCII text - --attachformat 1: Content-Type: text/plain; name="VERSION"; charset="us-ascii" Content-Description: VERSION Content-Disposition: attachment; filename="VERSION" - --attachformat 2: -Content-Type: text/plain; name="VERSION"; charset="us-ascii" -Content-Description: VERSION -Content-Disposition: attachment; filename="VERSION"; modification-date="Mon, 19 Dec 2005 22:39:51 -0600" .fi .PP If @@ -517,8 +488,6 @@ for more information. .RB ` \-noverbose ' .RB ` \-nowatch ' .RB ` "\-width\ 72" ' -.RB ` "\-attach\ Nmh-Attachment" ' -.RB ` "\-attachformat\ 1" ' .fi .SH CONTEXT None diff --git a/man/whatnow.man b/man/whatnow.man index 367a3267..c1f735b9 100644 --- a/man/whatnow.man +++ b/man/whatnow.man @@ -21,9 +21,6 @@ whatnow \- prompting front-end for sending messages .RI [ file ] .RB [ \-version ] .RB [ \-help ] -.RB [ \-attach -.IR header-field-name ] -.RB [ \-noattach ] .ad .SH DESCRIPTION .B Whatnow @@ -228,9 +225,6 @@ commands for managing MIME attachments. ^Editor:~^To override the default editor ^\-next:~^To name an editor to be used after exit ^~^from -^automimeproc:~^If value is 1, and the draft is a MIME -^~^composition file, then automatically call -^~^buildmimeproc prior to sending. ^buildmimeproc:~^Program to translate MIME composition files ^fileproc:~^Program to refile the message ^lproc:~^Program to list the contents of a message @@ -243,7 +237,6 @@ commands for managing MIME attachments. .SH DEFAULTS .nf .RB ` \-prompt "' defaults to \*(lqWhat\ Now?\ \*(rq" -.RB ` \-attach "' defaults to \*(lqNmh-Attachment\*(rq" .fi .SH BUGS If the initial edit fails, diff --git a/test/dist/test-dist b/test/dist/test-dist index 2bb1d30f..19ba6406 100755 --- a/test/dist/test-dist +++ b/test/dist/test-dist @@ -384,5 +384,26 @@ EOF test_dist +inbox 1 -noedit -to somebody@example.com -fcc +outbox run_test 'scan +outbox -width 6 2' ' 2 ' +# +# Check that dist encodes headers using RFC-2047 properly +# + +export LC_ALL=en_US.UTF-8 + +cat >"$expected" < +To: Some User +Date: Fri, 29 Sep 2006 00:00:00 +Message-Id: 1@test.nmh +Subject: Testing message 1 +Resent-From: =?UTF-8?Q?Mr_F=C3=B8o_Bar?= +Resent-To: =?UTF-8?Q?Mr_Nobod=C3=BF?= +Resent-Date: + +This is message number 1 +EOF + +test_dist +inbox 1 -noedit -from 'Mr Føo Bar ' \ + -to 'Mr Nobodÿ ' -fcc +outbox exit ${failed:-0} diff --git a/test/mhbuild/test-attach b/test/mhbuild/test-attach index 4eacc6e9..00fe1900 100755 --- a/test/mhbuild/test-attach +++ b/test/mhbuild/test-attach @@ -16,7 +16,6 @@ setup_test draft="$MH_TEST_DIR/$$.draft" expected="$MH_TEST_DIR/$$.expected" -actual="$MH_TEST_DIR/$$.actual" # # Test out a simple draft, one part. @@ -30,9 +29,9 @@ Attach: ${srcdir}/test/mhbuild/tiny.jpg ------ EOF -mhbuild "$draft" +run_prog mhbuild "$draft" -cat > "$actual" < "$expected" < cc: Fcc: +outbox @@ -45,7 +44,7 @@ Content-Transfer-Encoding: base64 /9g= EOF -check "$draft" "$actual" +check "$draft" "$expected" # # Check out more common case, one (or more) attachments @@ -61,12 +60,210 @@ Attach: ${srcdir}/test/mhbuild/tiny.jpg This is a test EOF -mhbuild "$draft" +run_prog mhbuild "$draft" -cat "$draft" +cat > "$expected" < +cc: +Fcc: +outbox +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" + +------- =_aaaaaaaaaa0 +Content-Type: text/plain; charset="us-ascii" + +This is a test + +------- =_aaaaaaaaaa0 +Content-Type: image/jpeg; name="tiny.jpg" +Content-Description: tiny.jpg +Content-Disposition: attachment; filename="tiny.jpg" +Content-Transfer-Encoding: base64 + +/9g= + +------- =_aaaaaaaaaa0-- +EOF + +check "$draft" "$expected" + +# +# An empty Attach header +# + +cat > "$draft" < +cc: +Fcc: +outbox +Attach: +------ +This is a test of an empty attach header. +EOF + +run_prog mhbuild "$draft" + +cat > "$expected" < +cc: +Fcc: +outbox +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" + +This is a test of an empty attach header. +EOF + +check "$draft" "$expected" + +# +# Check a completely empty message +# + +cat > "$draft" < +cc: +Fcc: +outbox +Subject: Test of an empty body +EOF + +run_prog mhbuild "$draft" + +cat > "$expected" < +cc: +Fcc: +outbox +Subject: Test of an empty body +MIME-Version: 1.0 +Content-Type: text/plain +EOF + +check "$draft" "$expected" + +# +# Make sure we fail if we run into a MIME-Version header +# + +cat > "$draft" < +cc: +Fcc: +outbox +Subject: Test of an already-MIMEified message +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" + +This is a preformatted MIME content test. +EOF + +set +e +run_test 'eval mhbuild "$draft"' "mhbuild: draft shouldn't contain MIME-Version: field" +set -e + +# +# Run it again using -auto +# + +run_prog mhbuild -auto "$draft" + +cat > "$expected" < +cc: +Fcc: +outbox +Subject: Test of an already-MIMEified message +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" + +This is a preformatted MIME content test. +EOF + +check "$draft" "$expected" + +# +# Make sure -dist does nothing but encode headers +# + +cat > "$draft" < +cc: +Fcc: +outbox +Subject: An empty dist test +EOF + +LC_ALL=en_US.UTF-8 run_prog mhbuild -dist "$draft" + +cat > "$expected" < +cc: +Fcc: +outbox +Subject: An empty dist test +EOF + +check "$draft" "$expected" # -# Two parts, one attachment +# Two parts, one attachment; make sure mixing of multiparts at different +# levels works # +cat > "$draft" < +cc: +Fcc: +outbox +Subject: A more complete multipart test +Attach: ${srcdir}/test/mhbuild/tiny.jpg +-------- +#begin alternative +# + +This is some HTML tëxt. + + +#end +EOF + +LC_ALL=en_US.UTF-8 run_prog mhbuild "$draft" + +cat > "$expected" < +cc: +Fcc: +outbox +Subject: A more complete multipart test +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" + +------- =_aaaaaaaaaa0 +Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1" + +------- =_aaaaaaaaaa1 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + +This is some t=C3=ABxt. + +------- =_aaaaaaaaaa1 +Content-Type: text/html; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + + + +This is some HTML t=C3=ABxt. + + + +------- =_aaaaaaaaaa1-- + +------- =_aaaaaaaaaa0 +Content-Type: image/jpeg; name="tiny.jpg" +Content-Description: tiny.jpg +Content-Disposition: attachment; filename="tiny.jpg" +Content-Transfer-Encoding: base64 + +/9g= + +------- =_aaaaaaaaaa0-- +EOF + +check "$draft" "$expected" + exit ${failed:-0} diff --git a/test/mhbuild/test-utf8-body b/test/mhbuild/test-utf8-body index e4a7c4e4..033a2ef8 100755 --- a/test/mhbuild/test-utf8-body +++ b/test/mhbuild/test-utf8-body @@ -54,7 +54,7 @@ cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Subject: Test -Nmh-Attachment: $MH_TEST_DIR/attachment.txt +Attach: $MH_TEST_DIR/attachment.txt This is a test. EOF @@ -91,7 +91,7 @@ cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Subject: Test -Nmh-Attachment: $MH_TEST_DIR/attachment.txt +Attach: $MH_TEST_DIR/attachment.txt ¡Ay, caramba! EOF diff --git a/test/mhmail/test-mhmail b/test/mhmail/test-mhmail index 043d95ef..ff9fd40b 100755 --- a/test/mhmail/test-mhmail +++ b/test/mhmail/test-mhmail @@ -292,6 +292,8 @@ RCPT TO: DATA To: recipient@example.com From: sender8@localhost +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: Message-ID: diff --git a/test/post/test-messageid b/test/post/test-messageid index 544af668..6ca8f97e 100755 --- a/test/post/test-messageid +++ b/test/post/test-messageid @@ -32,6 +32,8 @@ DATA From: Mr Nobody To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test @@ -122,6 +124,8 @@ cat > "${testname}.expected" < To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: Message-ID: @@ -145,6 +149,8 @@ cat > "${testname}.expected" < To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: Message-ID: diff --git a/test/post/test-mts b/test/post/test-mts index afcd1319..73b9aa11 100755 --- a/test/post/test-mts +++ b/test/post/test-mts @@ -30,6 +30,8 @@ DATA From: Mr Nobody To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test @@ -94,6 +96,8 @@ cat > "${testname}.expected" < To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test @@ -118,6 +122,8 @@ cat > "${testname}.expected" < To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test @@ -141,6 +147,8 @@ cat > "${testname}.expected1" < To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test @@ -157,6 +165,8 @@ Subject: Test From: Mr Nobody To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test diff --git a/test/post/test-post-aliases b/test/post/test-post-aliases index 62c1863b..664346df 100755 --- a/test/post/test-post-aliases +++ b/test/post/test-post-aliases @@ -86,6 +86,8 @@ cat >"${testname}.expected" < To: Blind List: ; Subject: blind list test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is test of a blind list. @@ -106,6 +108,8 @@ DATA From: Mr Nobody To: Blind List: ; Subject: blind list test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is test of a blind list. @@ -129,6 +133,8 @@ cat >"${testname}.expected" < To: "named.list" , "named.list" Subject: named list test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is test of a named list. diff --git a/test/post/test-post-basic b/test/post/test-post-basic index 74ef5e11..c198007b 100755 --- a/test/post/test-post-basic +++ b/test/post/test-post-basic @@ -34,6 +34,8 @@ DATA From: Mr Nobody To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test @@ -84,6 +86,8 @@ DATA From: Mr Nobody To: Somebody Else Subject: Test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test diff --git a/test/post/test-post-bcc b/test/post/test-post-bcc index e1a63549..fe8d5fd9 100755 --- a/test/post/test-post-bcc +++ b/test/post/test-post-bcc @@ -51,6 +51,8 @@ From: Mr Nobody To: Somebody One , Somebody Two Subject: Test Bcc +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is test of Bcc recipients. @@ -71,6 +73,8 @@ From: Mr Nobody To: Somebody One , Somebody Two Subject: Test Bcc +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is test of Bcc recipients. diff --git a/test/post/test-post-dcc b/test/post/test-post-dcc index f2bbda60..d9480da8 100755 --- a/test/post/test-post-dcc +++ b/test/post/test-post-dcc @@ -36,6 +36,8 @@ From: Mr Nobody To: Somebody One , Somebody Two Subject: Test Dcc +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is test of Dcc recipients. diff --git a/test/post/test-post-envelope b/test/post/test-post-envelope index 7d3288b0..b9e75cec 100755 --- a/test/post/test-post-envelope +++ b/test/post/test-post-envelope @@ -39,6 +39,8 @@ From: Mr Nobody One , Sender: Mr Nobody Three To: Somebody Else Subject: Sender test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test of the Sender header. @@ -73,6 +75,8 @@ From: Mr Nobody One , Sender: Mr Nobody Three To: Somebody Else Subject: Envelope-From test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a test of the Envelope-From header. @@ -106,6 +110,8 @@ From: Mr Nobody One , Mr Nobody Two To: Somebody Else Subject: Envelope-From and Sender test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: Sender: nobody4@example.com @@ -137,6 +143,8 @@ DATA From: Mr Nobody One To: Somebody Else Subject: Solo Envelope-From test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a solo test of the Envelope-From header. @@ -167,6 +175,8 @@ DATA From: Mr Nobody One To: Somebody Else Subject: Blank Envelope-From test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a blank test of the Envelope-From header. diff --git a/test/post/test-post-fcc b/test/post/test-post-fcc index 2fdd9deb..052e3dbf 100755 --- a/test/post/test-post-fcc +++ b/test/post/test-post-fcc @@ -34,6 +34,8 @@ DATA From: Mr Nobody To: Somebody Else Subject: Fcc test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a fcc test @@ -47,6 +49,8 @@ cat > "${testname}.msg.expected" < To: Somebody Else Subject: Fcc test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is a fcc test diff --git a/test/post/test-post-group b/test/post/test-post-group index d5e39ae6..59134b40 100755 --- a/test/post/test-post-group +++ b/test/post/test-post-group @@ -33,6 +33,8 @@ DATA From: Mr Nobody To: our-group: ; Subject: Group test +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is test of group recipients. diff --git a/test/post/test-post-multiple b/test/post/test-post-multiple index 4fe3e85c..f7d1a139 100755 --- a/test/post/test-post-multiple +++ b/test/post/test-post-multiple @@ -34,6 +34,8 @@ From: Mr Nobody To: Somebody One , Somebody Two Subject: Test multiple +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" Date: This is test of multiple recipients. diff --git a/test/whatnow/test-attach-detach b/test/whatnow/test-attach-detach index 3181f21b..ba22a19c 100755 --- a/test/whatnow/test-attach-detach +++ b/test/whatnow/test-attach-detach @@ -68,13 +68,13 @@ esac # whatnow's exit status is always 1 so that is not a failure set +e echo "attach $testname_quoted" | \ - run_prog whatnow -attach foo -noedit -prompt '' 2>>$actualerr >>$actual + run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual echo "alist" | \ - run_prog whatnow -attach foo -noedit -prompt '' 2>>$actualerr >>$actual + run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual echo "detach $testname_quoted" | \ - run_prog whatnow -attach foo -noedit -prompt '' 2>>$actualerr >>$actual + run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual echo "alist" | \ - run_prog whatnow -attach foo -noedit -prompt '' 2>>$actualerr >>$actual + run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual set -e check "$expectederr" "$actualerr" @@ -84,7 +84,7 @@ if [ "$readline" = 0 ]; then cat >"$expected" < [context]{attachment} ${MH_TEST_DIR}/Mail/context +Attaching ${MH_TEST_DIR}/Mail/context as a text/plain EOF else cat >"$expected" < [context]{attachment} ${MH_TEST_DIR}/Mail/context +Attaching ${MH_TEST_DIR}/Mail/context as a text/plain quit -delete EOF fi diff --git a/uip/attach.c b/uip/attach.c index 29024997..345c72a7 100644 --- a/uip/attach.c +++ b/uip/attach.c @@ -10,273 +10,10 @@ #include #include -static int get_line(FILE *, char *, size_t); #ifdef MIMETYPEPROC static char *get_file_info(const char *, const char *); #endif /* MIMETYPEPROC */ -int -attach(char *attachment_header_field_name, char *draft_file_name, - char *body_file_name, size_t body_file_name_len, - char *composition_file_name, size_t composition_file_name_len, - int attachformat) -{ - char buf[PATH_MAX + 6]; /* miscellaneous buffer */ - int c; /* current character for body copy */ - int has_attachment; /* draft has at least one attachment */ - int has_body; /* draft has a message body */ - int length; /* of attachment header field name */ - char *p; /* miscellaneous string pointer */ - struct stat st; /* file status buffer */ - FILE *body_file = NULL; /* body file pointer */ - FILE *draft_file; /* draft file pointer */ - int field_size; /* size of header field buffer */ - char *field; /* header field buffer */ - FILE *composition_file; /* composition file pointer */ - char *build_directive; /* mhbuild directive */ - - - /* - * Open up the draft file. - */ - - if ((draft_file = fopen(draft_file_name, "r")) == (FILE *)0) - adios(NULL, "can't open draft file `%s'.", draft_file_name); - - /* - * Allocate a buffer to hold the header components as they're read in. - * This buffer might need to be quite large, so we grow it as needed. - */ - - field = (char *)mh_xmalloc(field_size = 256); - - /* - * Scan the draft file for a header field name, with a non-empty - * body, that matches the -attach argument. The existence of one - * indicates that the draft has attachments. Bail out if there - * are no attachments because we're done. Read to the end of the - * headers even if we have no attachments. - */ - - length = strlen(attachment_header_field_name); - - has_attachment = 0; - - while (get_line(draft_file, field, field_size) != EOF && *field != '\0' && - *field != '-') { - if (strncasecmp(field, attachment_header_field_name, length) == 0 && - field[length] == ':') { - for (p = field + length + 1; *p == ' ' || *p == '\t'; p++) - ; - if (strlen (p) > 0) { - has_attachment = 1; - } - } - } - - if (has_attachment == 0) - return (DONE); - - /* - * We have at least one attachment. Look for at least one non-blank line - * in the body of the message which indicates content in the body. - */ - - has_body = 0; - - while (get_line(draft_file, field, field_size) != EOF) { - for (p = field; *p != '\0'; p++) { - if (*p != ' ' && *p != '\t') { - has_body = 1; - break; - } - } - - if (has_body) - break; - } - - /* - * Make names for the temporary files. - */ - - (void)strncpy(body_file_name, - m_mktemp(m_maildir(invo_name), NULL, NULL), - body_file_name_len); - (void)strncpy(composition_file_name, - m_mktemp(m_maildir(invo_name), NULL, NULL), - composition_file_name_len); - - if (has_body) - body_file = fopen(body_file_name, "w"); - - composition_file = fopen(composition_file_name, "w"); - - if ((has_body && body_file == (FILE *)0) || composition_file == (FILE *)0) { - clean_up_temporary_files(body_file_name, composition_file_name); - adios(NULL, "unable to open all of the temporary files."); - } - - /* - * Start at the beginning of the draft file. Copy all - * non-attachment header fields to the temporary composition - * file. Then add the dashed line separator. - */ - - rewind(draft_file); - - while (get_line(draft_file, field, field_size) != EOF && *field != '\0' && - *field != '-') - if (strncasecmp(field, attachment_header_field_name, length) != 0 || - field[length] != ':') - (void)fprintf(composition_file, "%s\n", field); - - (void)fputs("--------\n", composition_file); - - /* - * Copy the message body to a temporary file. - */ - - if (has_body) { - while ((c = getc(draft_file)) != EOF) - putc(c, body_file); - - (void)fclose(body_file); - } - - /* - * Add a mhbuild MIME composition file line for the body if there was one. - * Set the default content type to text/plain so that mhbuild takes care - * of any necessary encoding. - */ - - if (has_body) - /* - * Make sure that the attachment file exists and is readable. - */ - if (stat(body_file_name, &st) != OK || - access(body_file_name, R_OK) != OK) { - advise(NULL, "unable to access file \"%s\"", body_file_name); - return NOTOK; - } - - if ((build_directive = construct_build_directive (body_file_name, - "text/plain", - attachformat)) == NULL) { - clean_up_temporary_files(body_file_name, composition_file_name); - adios (NULL, "exiting due to failure in attach()"); - } else { - (void) fputs(build_directive, composition_file); - free(build_directive); - } - - /* - * Now, go back to the beginning of the draft file and look for - * header fields that specify attachments. Add a mhbuild MIME - * composition file for each. - */ - - rewind(draft_file); - - while (get_line(draft_file, field, field_size) != EOF && *field != '\0' && - *field != '-') { - if (strncasecmp(field, attachment_header_field_name, length) == 0 && - field[length] == ':') { - for (p = field + length + 1; *p == ' ' || *p == '\t'; p++) - ; - - /* Skip empty attachment_header_field_name lines. */ - if (strlen (p) > 0) { - struct stat st; - if (stat(p, &st) == OK && access(p, R_OK) == OK) { - if (S_ISREG (st.st_mode)) { - /* Don't set the default content type so that - construct_build_directive() will try to infer - it from the file type. */ - if ((build_directive = construct_build_directive (p, 0, - attachformat)) == NULL) { - clean_up_temporary_files(body_file_name, - composition_file_name); - adios (NULL, "exiting due to failure in attach()"); - } else { - (void) fputs(build_directive, composition_file); - free(build_directive); - } - } else { - adios (NULL, "unable to attach %s, not a plain file", - p); - } - } else { - adios (NULL, "unable to access file \"%s\"", p); - } - } - } - } - - (void)fclose(composition_file); - - /* - * We're ready to roll! Run mhbuild on the composition file. - * Note that mhbuild is in the context as buildmimeproc. - */ - - (void)sprintf(buf, "%s %s", buildmimeproc, composition_file_name); - - if (system(buf) != 0) { - clean_up_temporary_files(body_file_name, composition_file_name); - return NOTOK; - } - - return OK; -} - -void -clean_up_temporary_files(const char *body_file_name, - const char *composition_file_name) -{ - (void) unlink(body_file_name); - (void) unlink(composition_file_name); - - return; -} - -static int -get_line(FILE *draft_file, char *field, size_t field_size) -{ - int c; /* current character */ - size_t n; /* number of bytes in buffer */ - char *p; /* buffer pointer */ - - /* - * Get a line from the input file, growing the field buffer as - * needed. We do this so that we can fit an entire line in the - * buffer making it easy to do a string comparison on both the - * field name and the field body which might be a long path name. - */ - - for (n = 0, p = field; (c = getc(draft_file)) != EOF; *p++ = c) { - if (c == '\n' && (c = getc(draft_file)) != ' ' && c != '\t') { - (void)ungetc(c, draft_file); - c = '\n'; - break; - } - - if (++n >= field_size - 1) { - field = (char *)mh_xrealloc((void *)field, field_size += 256); - - p = field + n - 1; - } - } - - /* - * NUL-terminate the field.. - */ - - *p = '\0'; - - return (c); -} - /* * Try to use external command to determine mime type, and possibly * encoding. Caller is responsible for free'ing returned memory. @@ -381,212 +118,3 @@ get_file_info(const char *proc, const char *file_name) { return cp ? strdup(cp) : NULL; } #endif /* MIMETYPEPROC */ - - -/* - * Construct an mhbuild directive for the draft file. This starts - * with the content type. Append a file name attribute, and depending - * on attachformat value a private x-unix-mode attribute and a - * description obtained (if possible) by running the "file" command on - * the file. Caller is responsible for free'ing returned memory. - */ -char * -construct_build_directive (char *file_name, const char *default_content_type, - int attachformat) { - char *build_directive = NULL; /* Return value. */ - char *content_type; /* mime content type */ - char cmd[PATH_MAX + 8]; /* file command buffer */ - struct stat st; /* file status buffer */ - char *p; /* miscellaneous temporary variables */ - int c; /* current character */ - - if ((content_type = mime_type (file_name)) == NULL) { - /* - * Check the file name for a suffix. Scan the context for - * that suffix on a mhshow-suffix- entry. We use these - * entries to be compatible with mhnshow, and there's no - * reason to make the user specify each suffix twice. Context - * entries of the form "mhshow-suffix-contenttype" in the name - * have the suffix in the field, including the dot. - */ - struct node *np; /* context scan node pointer */ - static FILE *fp = NULL; /* pointer for mhn.defaults */ - - if (fp == NULL && (fp = fopen (p = etcpath ("mhn.defaults"), "r"))) { - readconfig ((struct node **) NULL, fp, p, 0); - fclose(fp); - } - - if ((p = strrchr(file_name, '.')) != NULL) { - for (np = m_defs; np; np = np->n_next) { - if (strncasecmp(np->n_name, "mhshow-suffix-", 14) == 0 && - strcasecmp(p, np->n_field ? np->n_field : "") == 0) { - content_type = strdup (np->n_name + 14); - break; - } - } - } - - if (content_type == NULL && default_content_type != NULL) { - content_type = strdup (default_content_type); - } - } - - /* - * No content type was found, either because there was no matching - * entry in the context or because the file name has no suffix. - * Open the file and check for non-ASCII characters. Choose the - * content type based on this check. - */ - if (content_type == NULL) { - int binary; /* binary character found flag */ - FILE *fp; - - if ((fp = fopen(file_name, "r")) == (FILE *)0) { - advise(NULL, "unable to access file \"%s\"", file_name); - return NULL; - } - - binary = 0; - - while ((c = getc(fp)) != EOF) { - if (c > 127 || c < 0) { - binary = 1; - break; - } - } - - (void) fclose(fp); - - content_type = - strdup (binary ? "application/octet-stream" : "text/plain"); - } - - switch (attachformat) { - case 0: { - struct stat st; - FILE *fp; - char m[4]; - - /* Insert name, file mode, and Content-Id. */ - if (stat(file_name, &st) != OK || access(file_name, R_OK) != OK) { - advise(NULL, "unable to access file \"%s\"", file_name); - return NULL; - } - - snprintf (m, sizeof m, "%.3ho", (unsigned short)(st.st_mode & 0777)); - build_directive = concat ("#", content_type, "; name=\"", - ((p = strrchr(file_name, '/')) == NULL) - ? file_name - : p + 1, - "\"; x-unix-mode=0", m, NULL); - - if (strlen(file_name) > PATH_MAX) { - advise(NULL, "attachment file name `%s' too long.", file_name); - return NULL; - } - - (void) sprintf(cmd, "file '%s'", file_name); - - if ((fp = popen(cmd, "r")) != NULL && - fgets(cmd, sizeof (cmd), fp) != NULL) { - *strchr(cmd, '\n') = '\0'; - - /* - * The output of the "file" command is of the form - * - * file: description - * - * Strip off the "file:" and subsequent white space. - */ - for (p = cmd; *p != '\0'; p++) { - if (*p == ':') { - for (p++; *p != '\0'; p++) { - if (*p != '\t') - break; - } - break; - } - } - - if (*p != '\0') { - /* Insert Content-Description. */ - build_directive = - concat (build_directive, " [ ", p, " ]", NULL); - } - - (void) pclose(fp); - } - break; - } - case 1: - if (stringdex (m_maildir(invo_name), file_name) == 0) { - /* Content had been placed by send into a temp file. - Don't generate Content-Disposition header, because - it confuses Microsoft Outlook, Build 10.0.6626, at - least. */ - build_directive = concat ("#", content_type, " <>", NULL); - } else { - /* Suppress Content-Id, insert simple Content-Disposition - and Content-Description with filename. - The Content-Disposition type needs to be "inline" for - MS Outlook and BlackBerry calendar programs to properly - handle a text/calendar attachment. */ - p = strrchr(file_name, '/'); - build_directive = concat ("#", content_type, "; name=\"", - (p == NULL) ? file_name : p + 1, - "\" <> [", - (p == NULL) ? file_name : p + 1, - "]{", - strcmp ("text/calendar", content_type) - ? "attachment" : "inline", - "}", NULL); - } - - break; - case 2: - if (stringdex (m_maildir(invo_name), file_name) == 0) { - /* Content had been placed by send into a temp file. - Don't generate Content-Disposition header, because - it confuses Microsoft Outlook, Build 10.0.6626, at - least. */ - build_directive = concat ("#", content_type, " <>", NULL); - } else { - /* Suppress Content-Id, insert Content-Disposition with - modification date and Content-Description wtih filename. - The Content-Disposition type needs to be "inline" for - MS Outlook and BlackBerry calendar programs to properly - handle a text/calendar attachment. */ - - if (stat(file_name, &st) != OK || access(file_name, R_OK) != OK) { - advise(NULL, "unable to access file \"%s\"", file_name); - return NULL; - } - - p = strrchr(file_name, '/'); - build_directive = concat ("#", content_type, "; name=\"", - (p == NULL) ? file_name : p + 1, - "\" <> [", - (p == NULL) ? file_name : p + 1, - "]{", - strcmp ("text/calendar", content_type) - ? "attachment" : "inline", - "; modification-date=\"", - dtime (&st.st_mtime, 0), - "}", NULL); - } - - break; - default: - advise (NULL, "unsupported attachformat %d", attachformat); - } - - free(content_type); - - /* - * Finish up with the file name. - */ - build_directive = concat (build_directive, " ", file_name, "\n", NULL); - - return build_directive; -} diff --git a/uip/mhbuild.c b/uip/mhbuild.c index 0af3c56f..85b5a21b 100644 --- a/uip/mhbuild.c +++ b/uip/mhbuild.c @@ -44,6 +44,7 @@ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) \ X("debug", -5, DEBUGSW) \ + X("dist", -4, DISTSW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(MHBUILD); @@ -103,7 +104,7 @@ int list_all_messages (CT *, int, int, int, int); int main (int argc, char **argv) { - int sizesw = 1, headsw = 1, directives = 1, autobuild = 0; + int sizesw = 1, headsw = 1, directives = 1, autobuild = 0, dist = 0; int *icachesw; char *cp, buf[BUFSIZ]; char buffer[BUFSIZ], *compfile = NULL; @@ -268,6 +269,9 @@ main (int argc, char **argv) case DEBUGSW: debugsw = 1; continue; + case DISTSW: + dist = 1; + continue; } } if (compfile) @@ -334,7 +338,7 @@ main (int argc, char **argv) unlink_infile = 1; /* build the content structures for MIME message */ - ct = build_mime (infile, autobuild, directives, header_encoding); + ct = build_mime (infile, autobuild, dist, directives, header_encoding); /* * If ct == NULL, that means that -auto was set and a MIME version @@ -364,7 +368,7 @@ main (int argc, char **argv) */ /* build the content structures for MIME message */ - ct = build_mime (compfile, autobuild, directives, header_encoding); + ct = build_mime (compfile, autobuild, dist, directives, header_encoding); /* * If ct == NULL, that means -auto was set and we found a MIME version diff --git a/uip/mhbuildsbr.c b/uip/mhbuildsbr.c index df9bf5b7..840f0467 100644 --- a/uip/mhbuildsbr.c +++ b/uip/mhbuildsbr.c @@ -80,7 +80,7 @@ void free_encoding (CT, int); static int init_decoded_content (CT); static void setup_attach_content(CT, char *); static char *fgetstr (char *, int, FILE *); -static int user_content (FILE *, char *, char *, CT *); +static int user_content (FILE *, char *, CT *); static void set_id (CT, int); static int compose_content (CT); static int scan_content (CT); @@ -129,7 +129,8 @@ static void directive_pop(void) */ CT -build_mime (char *infile, int autobuild, int directives, int header_encoding) +build_mime (char *infile, int autobuild, int dist, int directives, + int header_encoding) { int compnum, state; char buf[BUFSIZ], name[NAMESZ]; @@ -283,9 +284,12 @@ finish_field: * Now add the MIME-Version header field * to the list of header fields. */ - np = add (VRSN_FIELD, NULL); - vp = concat (" ", VRSN_VALUE, "\n", NULL); - add_header (ct, np, vp); + + if (! dist) { + np = add (VRSN_FIELD, NULL); + vp = concat (" ", VRSN_VALUE, "\n", NULL); + add_header (ct, np, vp); + } /* * We initally assume we will find multiple contents in the @@ -311,7 +315,7 @@ finish_field: struct part *part; CT p; - if (user_content (in, infile, buf, &p) == DONE) { + if (user_content (in, buf, &p) == DONE) { admonish (NULL, "ignoring spurious #end"); continue; } @@ -325,12 +329,6 @@ finish_field: part->mp_part = p; } - /* - * close the composition draft since - * it's not needed any longer. - */ - fclose (in); - /* * Add any Attach headers to the list of MIME parts at the end of the * message. @@ -369,9 +367,55 @@ finish_field: free(at_prev); } - /* check if any contents were found */ - if (!m->mp_parts) - adios (NULL, "no content directives found"); + /* + * To allow for empty message bodies, if we've found NO content at all + * yet cook up an empty text/plain part. + */ + + if (!m->mp_parts) { + CT p; + struct part *part; + struct text *t; + + if ((p = (CT) calloc (1, sizeof(*p))) == NULL) + adios(NULL, "out of memory"); + + init_decoded_content(p); + + if (get_ctinfo ("text/plain", p, 0) == NOTOK) + done (1); + + p->c_type = CT_TEXT; + p->c_subtype = TEXT_PLAIN; + p->c_encoding = CE_7BIT; + p->c_file = getcpy(infile); + /* + * Sigh. ce_file contains the "decoded" contents of this part. + * So this seems like the best option available since we're going + * to call scan_content() on this. + */ + p->c_cefile.ce_file = getcpy("/dev/null"); + p->c_begin = ftell(in); + p->c_end = ftell(in); + + if ((t = (struct text *) calloc (1, sizeof (*t))) == NULL) + adios (NULL, "out of memory"); + + t->tx_charset = CHARSET_SPECIFIED; + p->c_ctparams = t; + + if ((part = (struct part *) calloc (1, sizeof(*part))) == NULL) + adios (NULL, "out of memory"); + *pp = part; + pp = &part->mp_next; + part->mp_part = p; + } + + /* + * close the composition draft since + * it's not needed any longer. + */ + fclose (in); /* * If only one content was found, then remove and @@ -421,7 +465,8 @@ finish_field: } /* Build the rest of the header field structures */ - build_headers (ct); + if (! dist) + build_headers (ct); return ct; } @@ -487,7 +532,7 @@ fgetstr (char *s, int n, FILE *stream) */ static int -user_content (FILE *in, char *file, char *buf, CT *ctp) +user_content (FILE *in, char *buf, CT *ctp) { int extrnal, vrsn; char *cp, **ap; @@ -954,7 +999,7 @@ use_forw: struct part *part; CT p; - if (user_content (in, file, buffer, &p) == DONE) { + if (user_content (in, buffer, &p) == DONE) { if (!m->mp_parts) adios (NULL, "empty \"#begin ... #end\" sequence"); return OK; diff --git a/uip/mhmail b/uip/mhmail index 916732d8..a0baf2e9 100755 --- a/uip/mhmail +++ b/uip/mhmail @@ -84,8 +84,7 @@ fi tolist= ## To: addresses toarg=0 ## whether currently handling -to attacharg=0 ## whether currently handling -attach -attach_send_switch_added=0 ## whether added "-attach Nmh-Attachment" switch -attachind=Nmh-Attachment ## attachment indicator +attachind=Attach ## attachment indicator body= ## contents of the message body bodyarg=0 ## whether currently handling -body cclist= ## Cc: addresses @@ -114,11 +113,7 @@ for arg in "$@"; do mhmailswitch=1 attacharg=1 use_send=1 - if [ $attach_send_switch_added -eq 0 ]; then - #### Override any send -attach switch in user's profile. - postsendargs="${postsendargs:+$postsendargs }-attach $attachind" - attach_send_switch_added=1 - fi ;; + ;; -b|-bo|-bod|-body) mhmailswitch=1; bodyarg=1 ;; -c|-cc) mhmailswitch=1; ccarg=1 ;; -f|-fr|-fro|-from) mhmailswitch=1; fromarg=1 ;; diff --git a/uip/send.c b/uip/send.c index be5dc793..626eba16 100644 --- a/uip/send.c +++ b/uip/send.c @@ -62,8 +62,8 @@ X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \ X("saslmech mechanism", SASLminc(-5), SASLMECHSW) \ X("user username", SASLminc(-4), USERSW) \ - X("attach", 6, ATTACHSW) \ - X("noattach", 0, NOATTACHSW) \ + X("attach", -6, ATTACHSW) \ + X("noattach", -8, NOATTACHSW) \ X("attachformat", 7, ATTACHFORMATSW) \ X("port server-port-name/number", 4, PORTSW) \ X("tls", TLSminc(-3), TLSSW) \ @@ -117,8 +117,6 @@ main (int argc, char **argv) char *msgs[MAXARGS], **vec; struct msgs *mp; struct stat st; - char *attach = NMH_ATTACH_HEADER; /* header field name for attachments */ - int attachformat = 1; /* mhbuild format specifier for attachments */ setlocale(LC_ALL, ""); invo_name = r1bindex (argv[0], '/'); @@ -271,26 +269,14 @@ main (int argc, char **argv) continue; case ATTACHSW: - if (!(attach = *argp++) || *attach == '-') - adios (NULL, "missing argument to %s", argp[-2]); + advise(NULL, "The -attach switch is deprecated"); continue; case NOATTACHSW: - attach = NULL; + advise(NULL, "The -noattach switch is deprecated"); continue; case ATTACHFORMATSW: - if (! *argp || **argp == '-') - adios (NULL, "missing argument to %s", argp[-1]); - else { - attachformat = atoi (*argp); - if (attachformat < 0 || - attachformat > ATTACHFORMATS - 1) { - advise (NULL, "unsupported attachformat %d", - attachformat); - continue; - } - } - ++argp; + advise(NULL, "The -attachformat switch is deprecated"); continue; } } else { @@ -438,8 +424,7 @@ go_to_it: closefds (3); for (msgnum = 0; msgnum < msgp; msgnum++) { - switch (sendsbr (vec, vecp, program, msgs[msgnum], &st, 1, attach, - attachformat)) { + switch (sendsbr (vec, vecp, program, msgs[msgnum], &st, 1)) { case DONE: done (++status); case NOTOK: diff --git a/uip/sendsbr.c b/uip/sendsbr.c index 2b946689..fd80a0f0 100644 --- a/uip/sendsbr.c +++ b/uip/sendsbr.c @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef HAVE_SYS_TIME_H # include @@ -34,12 +35,6 @@ char *distfile = NULL; static jmp_buf env; -/* - * external prototypes - */ -int sendsbr (char **, int, char *, char *, struct stat *, int, char *, int); -char *getusername (void); - /* * static prototypes */ @@ -58,47 +53,41 @@ static int sendaux (char **, int, char *, char *, struct stat *); int sendsbr (char **vec, int vecp, char *program, char *drft, struct stat *st, - int rename_drft, char *attachment_header_field_name, int attachformat) + int rename_drft) { - int status; + int status, i; + pid_t child; char buffer[BUFSIZ], file[BUFSIZ]; struct stat sts; - char *original_draft; /* name of original draft file */ - char *p; /* string pointer for building file name */ - char composition_file_name[PATH_MAX + 1]; /* name of mhbuild composition temporary file */ - char body_file_name[PATH_MAX + 1]; /* name of temporary file for body content */ - - /* - * Save the original name of the draft file. The name of the draft file is changed - * to a temporary file containing the built MIME message if there are attachments. - * We need the original name so that it can be renamed after the message is sent. - */ - - original_draft = drft; + char **buildvec, *buildprogram; /* - * There might be attachments if a header field name for attachments is supplied. - * Convert the draft to a MIME message. Use the mhbuild composition file for the - * draft if there was a successful conversion because that now contains the MIME - * message. A nice side effect of this is that it leaves the original draft file - * untouched so that it can be retrieved and modified if desired. + * Run the mimebuildproc (which is by default mhbuild) on the message + * with the addition of the "-auto" flag */ - if (attachment_header_field_name != (char *)0) { - switch (attach(attachment_header_field_name, drft, - body_file_name, sizeof body_file_name, - composition_file_name, sizeof composition_file_name, - attachformat)) { - case OK: - drft = composition_file_name; - break; + switch (child = fork()) { + case NOTOK: + adios("fork", "unable to"); + break; - case NOTOK: - return (NOTOK); + case OK: + buildvec = argsplit(buildmimeproc, &buildprogram, &i); + buildvec[i++] = "-auto"; + if (distfile) + buildvec[i++] = "-dist"; + buildvec[i++] = drft; + buildvec[i] = NULL; + execvp(buildprogram, buildvec); + fprintf(stderr, "unable to exec "); + perror(buildmimeproc); + _exit(-1); + break; - case DONE: - break; - } + default: + if (pidXwait(child, buildmimeproc)) + return NOTOK; + break; } done=armed_done; @@ -131,7 +120,7 @@ sendsbr (char **vec, int vecp, char *program, char *drft, struct stat *st, /* rename the original draft */ if (rename_drft && status == OK && - rename (original_draft, strncpy (buffer, m_backup (original_draft), sizeof(buffer))) == NOTOK) + rename (drft, strncpy (buffer, m_backup (drft), sizeof(buffer))) == NOTOK) advise (buffer, "unable to rename %s to", drft); break; @@ -144,33 +133,6 @@ sendsbr (char **vec, int vecp, char *program, char *drft, struct stat *st, if (distfile) unlink (distfile); - /* - * Get rid of any temporary files that we created for attachments. Also get rid of - * the renamed composition file that mhbuild leaves as a turd. It looks confusing, - * but we use the body file name to help build the renamed composition file name. - */ - - if (drft == composition_file_name) { - clean_up_temporary_files(body_file_name, composition_file_name); - - if (strlen(composition_file_name) >= sizeof (composition_file_name) - 6) - advise((char *)0, "unable to remove original composition file."); - - else { - if ((p = strrchr(composition_file_name, '/')) == (char *)0) - p = composition_file_name; - else - p++; - - (void)strcpy(body_file_name, p); - *p++ = ','; - (void)strcpy(p, body_file_name); - (void)strcat(p, ".orig"); - - (void)unlink(composition_file_name); - } - } - return status; } diff --git a/uip/viamail.c b/uip/viamail.c index 39ccf509..13447382 100644 --- a/uip/viamail.c +++ b/uip/viamail.c @@ -54,16 +54,13 @@ main (int argc, char **argv) int delay = 0; char *f1 = NULL, *f2 = NULL, *f3 = NULL; char *f4 = NULL, *f5 = NULL, *f7 = NULL; - static char postpath[PATH_MAX]; char *cp, buf[BUFSIZ]; char **argp, **arguments; setlocale(LC_ALL, ""); invo_name = r1bindex (argv[0], '/'); - /* foil search of user profile/context */ - if (context_foil (NULL) == -1) - done (1); + context_read(); arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; @@ -138,34 +135,6 @@ main (int argc, char **argv) if (!f1) adios (NULL, "missing -viamail \"mailpath\" switch"); - /* viamail doesn't read the context and postproc isn't always what - we want, such as when running make distcheck. If we have the - absolute path, set postproc to point to post in the same - directory as this executable. - This could be generalized to handle relative paths (by - converting to absolute), to find the full path from PATH given - just the basename, and to squash out ../ but it's only needed - here. viamail is typically called from sendfiles, which - provides the absolute path. - */ - if (argv[0] && argv[0][0] == '/' && - strlen(argv[0]) - 3 < sizeof postpath) { - strncpy (postpath, argv[0], sizeof postpath - 1); - postpath[sizeof postpath - 1] = '\0'; - if ((cp = strrchr (postpath, '/'))) { - struct stat st; - - *(cp + 1) = '\0'; - /* strlen ("post") <= sizeof postpath - (cp - postpath) - 2 - but use strncat just in case the code above changes. */ - strncat (postpath, "post", sizeof postpath - (cp - postpath) - 2); - - if (stat (postpath, &st) == OK) { - postproc = postpath; - } - } - } - via_mail (f1, f2, f3, f4, f5, delay, f7); return 0; /* dead code to satisfy the compiler */ } @@ -248,7 +217,7 @@ via_mail (char *mailsw, char *subjsw, char *parmsw, char *descsw, vec[vecp++] = cp; } - switch (sendsbr (vec, vecp, program, tmpfil, &st, 0, (char *)0, 0)) { + switch (sendsbr (vec, vecp, program, tmpfil, &st, 0)) { case DONE: case NOTOK: status++; diff --git a/uip/whatnowsbr.c b/uip/whatnowsbr.c index 7c2c021b..6149c125 100644 --- a/uip/whatnowsbr.c +++ b/uip/whatnowsbr.c @@ -53,8 +53,9 @@ X("prompt string", 4, PRMPTSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) \ - X("attach header-field-name", 0, ATTACHSW) \ - X("noattach", 0, NOATTACHSW) \ + X("attach header-field-name", -6, ATTACHSW) \ + X("noattach", -8, NOATTACHSW) \ + #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(WHATNOW); @@ -122,7 +123,6 @@ WhatNow (int argc, char **argv) char buf[BUFSIZ], prompt[BUFSIZ]; char **argp, **arguments; struct stat st; - char *attach = NMH_ATTACH_HEADER;/* attachment header field name */ char cwd[PATH_MAX + 1]; /* current working directory */ char file[PATH_MAX + 1]; /* file name buffer */ char shell[PATH_MAX + 1]; /* shell response buffer */ @@ -197,12 +197,11 @@ WhatNow (int argc, char **argv) continue; case ATTACHSW: - if (!(attach = *argp++) || *attach == '-') - adios (NULL, "missing argument to %s", argp[-2]); + advise(NULL, "The -attach switch is deprecated"); continue; case NOATTACHSW: - attach = NULL; + advise(NULL, "The -noattach switch is deprecated"); continue; } } @@ -360,11 +359,6 @@ WhatNow (int argc, char **argv) * -n numbers listing */ - if (attach == (char *)0) { - advise((char *)0, "can't list because no header field name was given."); - break; - } - l = (char *)0; n = 0; @@ -390,7 +384,7 @@ WhatNow (int argc, char **argv) advise((char *)0, "usage is alist [-ln]."); else - annolist(drft, attach, l, n); + annolist(drft, ATTACH_FIELD, l, n); break; @@ -402,11 +396,6 @@ WhatNow (int argc, char **argv) int verbose = 0; char **ap; - if (attach == (char *)0) { - advise((char *)0, "can't attach because no header field name was given."); - break; - } - for (ap = argp+1; *ap; ++ap) { if (strcmp(*ap, "-v") == 0) { ++argp; @@ -437,28 +426,25 @@ WhatNow (int argc, char **argv) if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) { while (fgets(shell, sizeof (shell), f) != (char *)0) { - char *build_directive; + char *ctype; *(strchr(shell, '\n')) = '\0'; if (*shell == '/') { - (void)annotate(drft, attach, shell, 1, 0, -2, 1); - if (verbose) { - build_directive = - construct_build_directive (shell, NULL, 1); - } + strncpy(file, shell, sizeof(file)); + file[sizeof(file) - 1] = '\0'; } else { - (void)sprintf(file, "%s/%s", cwd, shell); - (void)annotate(drft, attach, file, 1, 0, -2, 1); - if (verbose) { - build_directive = - construct_build_directive (file, NULL, 1); - } + snprintf(file, sizeof(file), "%s/%s", cwd, shell); + } + + annotate(drft, ATTACH_FIELD, file, 1, 0, -2, 1); + if (verbose) { + ctype = mime_type(file); } if (verbose) { - printf ("%s", build_directive); - free (build_directive); + printf ("Attaching %s as a %s", file, ctype); + free (ctype); } } @@ -475,11 +461,6 @@ WhatNow (int argc, char **argv) * Detach files from current draft. */ - if (attach == (char *)0) { - advise((char *)0, "can't detach because no header field name was given."); - break; - } - /* * Scan the arguments for a -n. Mixed file names and numbers aren't allowed, * so this catches a -n anywhere in the argument list. @@ -506,7 +487,7 @@ WhatNow (int argc, char **argv) if (**arguments != '\0') { n = atoi(*arguments); - (void)annotate(drft, attach, (char *)0, 1, 0, n, 1); + annotate(drft, ATTACH_FIELD, (char *)0, 1, 0, n, 1); for (argp = arguments + 1; *argp != (char *)0; argp++) { if (atoi(*argp) > n) { @@ -533,7 +514,7 @@ WhatNow (int argc, char **argv) if ((f = popen_in_dir(cwd, buf, "r")) != (FILE *)0) { while (fgets(shell, sizeof (shell), f) != (char *)0) { *(strchr(shell, '\n')) = '\0'; - (void)annotate(drft, attach, shell, 1, 0, 0, 1); + annotate(drft, ATTACH_FIELD, shell, 1, 0, 0, 1); } pclose(f); } else { @@ -822,19 +803,6 @@ sendfile (char **arg, char *file, int pushsw) int i, vecp; char *cp, *sp, **vec, *program; - /* Translate MIME composition file, if necessary */ - if ((cp = context_find ("automimeproc")) - && (!strcmp (cp, "1")) - && check_draft (file) - && (buildfile (NULL, file) == NOTOK)) - return 0; - - /* For backwards compatibility */ - if ((cp = context_find ("automhnproc")) - && check_draft (file) - && (i = editfile (&cp, NULL, file, NOUSE, NULL, NULL, NULL, 0, 0))) - return 0; - /* * If the sendproc is the nmh command `send', then we call * those routines directly rather than exec'ing the command. @@ -1066,9 +1034,6 @@ sendit (char *sp, char **arg, char *file, int pushed) char *cp, buf[BUFSIZ], **argp, *program; char **arguments, *savearg[MAXARGS], **vec; struct stat st; - char *attach = NMH_ATTACH_HEADER;/* attachment header field name */ - int attachformat = 1; /* mhbuild format specifier for - attachments */ #ifndef lint int distsw = 0; @@ -1246,28 +1211,14 @@ sendit (char *sp, char **arg, char *file, int pushed) continue; case SNDATTACHSW: - if (!(attach = *argp++) || *attach == '-') { - advise (NULL, "missing argument to %s", argp[-2]); - return; - } + advise(NULL, "The -attach switch is deprecated"); continue; case SNDNOATTACHSW: - attach = NULL; + advise(NULL, "The -noattach switch is deprecated"); continue; case SNDATTACHFORMAT: - if (! *argp || **argp == '-') - adios (NULL, "missing argument to %s", argp[-1]); - else { - attachformat = atoi (*argp); - if (attachformat < 0 || - attachformat > ATTACHFORMATS - 1) { - advise (NULL, "unsupported attachformat %d", - attachformat); - continue; - } - } - ++argp; + advise(NULL, "The -attachformat switch is deprecated"); continue; } } @@ -1322,7 +1273,7 @@ sendit (char *sp, char **arg, char *file, int pushed) closefds (3); - if (sendsbr (vec, vecp, program, file, &st, 1, attach, attachformat) == OK) + if (sendsbr (vec, vecp, program, file, &st, 1) == OK) done (0); }