Merge branch 'jk/maint-1.6.0-trace-argv'
[git] / t / t9001-send-email.sh
1 #!/bin/sh
2
3 test_description='git send-email'
4 . ./test-lib.sh
5
6 if ! test_have_prereq PERL; then
7         say 'skipping git send-email tests, perl not available'
8         test_done
9 fi
10
11 PROG='git send-email'
12 test_expect_success \
13     'prepare reference tree' \
14     'echo "1A quick brown fox jumps over the" >file &&
15      echo "lazy dog" >>file &&
16      git add file &&
17      GIT_AUTHOR_NAME="A" git commit -a -m "Initial."'
18
19 test_expect_success \
20     'Setup helper tool' \
21     '(echo "#!$SHELL_PATH"
22       echo shift
23       echo output=1
24       echo "while test -f commandline\$output; do output=\$((\$output+1)); done"
25       echo for a
26       echo do
27       echo "  echo \"!\$a!\""
28       echo "done >commandline\$output"
29       echo "cat > msgtxt\$output"
30       ) >fake.sendmail &&
31      chmod +x ./fake.sendmail &&
32      git add fake.sendmail &&
33      GIT_AUTHOR_NAME="A" git commit -a -m "Second."'
34
35 clean_fake_sendmail() {
36         rm -f commandline* msgtxt*
37 }
38
39 test_expect_success 'Extract patches' '
40     patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1`
41 '
42
43 # Test no confirm early to ensure remaining tests will not hang
44 test_no_confirm () {
45         rm -f no_confirm_okay
46         echo n | \
47                 GIT_SEND_EMAIL_NOTTY=1 \
48                 git send-email \
49                 --from="Example <from@example.com>" \
50                 --to=nobody@example.com \
51                 --smtp-server="$(pwd)/fake.sendmail" \
52                 $@ \
53                 $patches > stdout &&
54                 test_must_fail grep "Send this email" stdout &&
55                 > no_confirm_okay
56 }
57
58 # Exit immediately to prevent hang if a no-confirm test fails
59 check_no_confirm () {
60         test -f no_confirm_okay || {
61                 say 'No confirm test failed; skipping remaining tests to prevent hanging'
62                 test_done
63         }
64 }
65
66 test_expect_success 'No confirm with --suppress-cc' '
67         test_no_confirm --suppress-cc=sob
68 '
69 check_no_confirm
70
71 test_expect_success 'No confirm with --confirm=never' '
72         test_no_confirm --confirm=never
73 '
74 check_no_confirm
75
76 # leave sendemail.confirm set to never after this so that none of the
77 # remaining tests prompt unintentionally.
78 test_expect_success 'No confirm with sendemail.confirm=never' '
79         git config sendemail.confirm never &&
80         test_no_confirm --compose --subject=foo
81 '
82 check_no_confirm
83
84 test_expect_success 'Send patches' '
85      git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
86 '
87
88 cat >expected <<\EOF
89 !nobody@example.com!
90 !author@example.com!
91 !one@example.com!
92 !two@example.com!
93 EOF
94 test_expect_success \
95     'Verify commandline' \
96     'test_cmp expected commandline1'
97
98 cat >expected-show-all-headers <<\EOF
99 0001-Second.patch
100 (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
101 (mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
102 (mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
103 Dry-OK. Log says:
104 Server: relay.example.com
105 MAIL FROM:<from@example.com>
106 RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<bcc@example.com>
107 From: Example <from@example.com>
108 To: to@example.com
109 Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com
110 Subject: [PATCH 1/1] Second.
111 Date: DATE-STRING
112 Message-Id: MESSAGE-ID-STRING
113 X-Mailer: X-MAILER-STRING
114 In-Reply-To: <unique-message-id@example.com>
115 References: <unique-message-id@example.com>
116
117 Result: OK
118 EOF
119
120 test_expect_success 'Show all headers' '
121         git send-email \
122                 --dry-run \
123                 --suppress-cc=sob \
124                 --from="Example <from@example.com>" \
125                 --to=to@example.com \
126                 --cc=cc@example.com \
127                 --bcc=bcc@example.com \
128                 --in-reply-to="<unique-message-id@example.com>" \
129                 --smtp-server relay.example.com \
130                 $patches |
131         sed     -e "s/^\(Date:\).*/\1 DATE-STRING/" \
132                 -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
133                 -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
134                 >actual-show-all-headers &&
135         test_cmp expected-show-all-headers actual-show-all-headers
136 '
137
138 test_expect_success 'Prompting works' '
139         clean_fake_sendmail &&
140         (echo "Example <from@example.com>"
141          echo "to@example.com"
142          echo ""
143         ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
144                 --smtp-server="$(pwd)/fake.sendmail" \
145                 $patches \
146                 2>errors &&
147                 grep "^From: Example <from@example.com>$" msgtxt1 &&
148                 grep "^To: to@example.com$" msgtxt1
149 '
150
151 z8=zzzzzzzz
152 z64=$z8$z8$z8$z8$z8$z8$z8$z8
153 z512=$z64$z64$z64$z64$z64$z64$z64$z64
154 test_expect_success 'reject long lines' '
155         clean_fake_sendmail &&
156         cp $patches longline.patch &&
157         echo $z512$z512 >>longline.patch &&
158         test_must_fail git send-email \
159                 --from="Example <nobody@example.com>" \
160                 --to=nobody@example.com \
161                 --smtp-server="$(pwd)/fake.sendmail" \
162                 $patches longline.patch \
163                 2>errors &&
164         grep longline.patch errors
165 '
166
167 test_expect_success 'no patch was sent' '
168         ! test -e commandline1
169 '
170
171 test_expect_success 'Author From: in message body' '
172         clean_fake_sendmail &&
173         git send-email \
174                 --from="Example <nobody@example.com>" \
175                 --to=nobody@example.com \
176                 --smtp-server="$(pwd)/fake.sendmail" \
177                 $patches &&
178         sed "1,/^$/d" < msgtxt1 > msgbody1
179         grep "From: A <author@example.com>" msgbody1
180 '
181
182 test_expect_success 'Author From: not in message body' '
183         clean_fake_sendmail &&
184         git send-email \
185                 --from="A <author@example.com>" \
186                 --to=nobody@example.com \
187                 --smtp-server="$(pwd)/fake.sendmail" \
188                 $patches &&
189         sed "1,/^$/d" < msgtxt1 > msgbody1
190         ! grep "From: A <author@example.com>" msgbody1
191 '
192
193 test_expect_success 'allow long lines with --no-validate' '
194         git send-email \
195                 --from="Example <nobody@example.com>" \
196                 --to=nobody@example.com \
197                 --smtp-server="$(pwd)/fake.sendmail" \
198                 --novalidate \
199                 $patches longline.patch \
200                 2>errors
201 '
202
203 test_expect_success 'Invalid In-Reply-To' '
204         clean_fake_sendmail &&
205         git send-email \
206                 --from="Example <nobody@example.com>" \
207                 --to=nobody@example.com \
208                 --in-reply-to=" " \
209                 --smtp-server="$(pwd)/fake.sendmail" \
210                 $patches
211                 2>errors
212         ! grep "^In-Reply-To: < *>" msgtxt1
213 '
214
215 test_expect_success 'Valid In-Reply-To when prompting' '
216         clean_fake_sendmail &&
217         (echo "From Example <from@example.com>"
218          echo "To Example <to@example.com>"
219          echo ""
220         ) | env GIT_SEND_EMAIL_NOTTY=1 git send-email \
221                 --smtp-server="$(pwd)/fake.sendmail" \
222                 $patches 2>errors &&
223         ! grep "^In-Reply-To: < *>" msgtxt1
224 '
225
226 test_expect_success 'setup fake editor' '
227         (echo "#!$SHELL_PATH" &&
228          echo "echo fake edit >>\"\$1\""
229         ) >fake-editor &&
230         chmod +x fake-editor
231 '
232
233 test_set_editor "$(pwd)/fake-editor"
234
235 test_expect_success '--compose works' '
236         clean_fake_sendmail &&
237         git send-email \
238         --compose --subject foo \
239         --from="Example <nobody@example.com>" \
240         --to=nobody@example.com \
241         --smtp-server="$(pwd)/fake.sendmail" \
242         $patches \
243         2>errors
244 '
245
246 test_expect_success 'first message is compose text' '
247         grep "^fake edit" msgtxt1
248 '
249
250 test_expect_success 'second message is patch' '
251         grep "Subject:.*Second" msgtxt2
252 '
253
254 cat >expected-suppress-sob <<\EOF
255 0001-Second.patch
256 (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
257 (mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
258 (mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
259 Dry-OK. Log says:
260 Server: relay.example.com
261 MAIL FROM:<from@example.com>
262 RCPT TO:<to@example.com>,<cc@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
263 From: Example <from@example.com>
264 To: to@example.com
265 Cc: cc@example.com, A <author@example.com>, One <one@example.com>, two@example.com
266 Subject: [PATCH 1/1] Second.
267 Date: DATE-STRING
268 Message-Id: MESSAGE-ID-STRING
269 X-Mailer: X-MAILER-STRING
270
271 Result: OK
272 EOF
273
274 test_suppression () {
275         git send-email \
276                 --dry-run \
277                 --suppress-cc=$1 \
278                 --from="Example <from@example.com>" \
279                 --to=to@example.com \
280                 --smtp-server relay.example.com \
281                 $patches |
282         sed     -e "s/^\(Date:\).*/\1 DATE-STRING/" \
283                 -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
284                 -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
285                 >actual-suppress-$1 &&
286         test_cmp expected-suppress-$1 actual-suppress-$1
287 }
288
289 test_expect_success 'sendemail.cc set' '
290         git config sendemail.cc cc@example.com &&
291         test_suppression sob
292 '
293
294 cat >expected-suppress-sob <<\EOF
295 0001-Second.patch
296 (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
297 (mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
298 (mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
299 Dry-OK. Log says:
300 Server: relay.example.com
301 MAIL FROM:<from@example.com>
302 RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
303 From: Example <from@example.com>
304 To: to@example.com
305 Cc: A <author@example.com>, One <one@example.com>, two@example.com
306 Subject: [PATCH 1/1] Second.
307 Date: DATE-STRING
308 Message-Id: MESSAGE-ID-STRING
309 X-Mailer: X-MAILER-STRING
310
311 Result: OK
312 EOF
313
314 test_expect_success 'sendemail.cc unset' '
315         git config --unset sendemail.cc &&
316         test_suppression sob
317 '
318
319 cat >expected-suppress-all <<\EOF
320 0001-Second.patch
321 Dry-OK. Log says:
322 Server: relay.example.com
323 MAIL FROM:<from@example.com>
324 RCPT TO:<to@example.com>
325 From: Example <from@example.com>
326 To: to@example.com
327 Subject: [PATCH 1/1] Second.
328 Date: DATE-STRING
329 Message-Id: MESSAGE-ID-STRING
330 X-Mailer: X-MAILER-STRING
331
332 Result: OK
333 EOF
334
335 test_expect_success '--suppress-cc=all' '
336         test_suppression all
337 '
338
339 cat >expected-suppress-body <<\EOF
340 0001-Second.patch
341 (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
342 (mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
343 (mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
344 Dry-OK. Log says:
345 Server: relay.example.com
346 MAIL FROM:<from@example.com>
347 RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
348 From: Example <from@example.com>
349 To: to@example.com
350 Cc: A <author@example.com>, One <one@example.com>, two@example.com
351 Subject: [PATCH 1/1] Second.
352 Date: DATE-STRING
353 Message-Id: MESSAGE-ID-STRING
354 X-Mailer: X-MAILER-STRING
355
356 Result: OK
357 EOF
358
359 test_expect_success '--suppress-cc=body' '
360         test_suppression body
361 '
362
363 cat >expected-suppress-sob <<\EOF
364 0001-Second.patch
365 (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
366 (mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
367 (mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
368 Dry-OK. Log says:
369 Server: relay.example.com
370 MAIL FROM:<from@example.com>
371 RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>
372 From: Example <from@example.com>
373 To: to@example.com
374 Cc: A <author@example.com>, One <one@example.com>, two@example.com
375 Subject: [PATCH 1/1] Second.
376 Date: DATE-STRING
377 Message-Id: MESSAGE-ID-STRING
378 X-Mailer: X-MAILER-STRING
379
380 Result: OK
381 EOF
382
383 test_expect_success '--suppress-cc=sob' '
384         test_suppression sob
385 '
386
387 cat >expected-suppress-bodycc <<\EOF
388 0001-Second.patch
389 (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
390 (mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
391 (mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
392 (body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
393 Dry-OK. Log says:
394 Server: relay.example.com
395 MAIL FROM:<from@example.com>
396 RCPT TO:<to@example.com>,<author@example.com>,<one@example.com>,<two@example.com>,<committer@example.com>
397 From: Example <from@example.com>
398 To: to@example.com
399 Cc: A <author@example.com>, One <one@example.com>, two@example.com, C O Mitter <committer@example.com>
400 Subject: [PATCH 1/1] Second.
401 Date: DATE-STRING
402 Message-Id: MESSAGE-ID-STRING
403 X-Mailer: X-MAILER-STRING
404
405 Result: OK
406 EOF
407
408 test_expect_success '--suppress-cc=bodycc' '
409         test_suppression bodycc
410 '
411
412 cat >expected-suppress-cc <<\EOF
413 0001-Second.patch
414 (mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
415 (body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
416 Dry-OK. Log says:
417 Server: relay.example.com
418 MAIL FROM:<from@example.com>
419 RCPT TO:<to@example.com>,<author@example.com>,<committer@example.com>
420 From: Example <from@example.com>
421 To: to@example.com
422 Cc: A <author@example.com>, C O Mitter <committer@example.com>
423 Subject: [PATCH 1/1] Second.
424 Date: DATE-STRING
425 Message-Id: MESSAGE-ID-STRING
426 X-Mailer: X-MAILER-STRING
427
428 Result: OK
429 EOF
430
431 test_expect_success '--suppress-cc=cc' '
432         test_suppression cc
433 '
434
435 test_confirm () {
436         echo y | \
437                 GIT_SEND_EMAIL_NOTTY=1 \
438                 git send-email \
439                 --from="Example <nobody@example.com>" \
440                 --to=nobody@example.com \
441                 --smtp-server="$(pwd)/fake.sendmail" \
442                 $@ $patches > stdout &&
443         grep "Send this email" stdout
444 }
445
446 test_expect_success '--confirm=always' '
447         test_confirm --confirm=always --suppress-cc=all
448 '
449
450 test_expect_success '--confirm=auto' '
451         test_confirm --confirm=auto
452 '
453
454 test_expect_success '--confirm=cc' '
455         test_confirm --confirm=cc
456 '
457
458 test_expect_success '--confirm=compose' '
459         test_confirm --confirm=compose --compose
460 '
461
462 test_expect_success 'confirm by default (due to cc)' '
463         CONFIRM=$(git config --get sendemail.confirm) &&
464         git config --unset sendemail.confirm &&
465         test_confirm
466         ret="$?"
467         git config sendemail.confirm ${CONFIRM:-never}
468         test $ret = "0"
469 '
470
471 test_expect_success 'confirm by default (due to --compose)' '
472         CONFIRM=$(git config --get sendemail.confirm) &&
473         git config --unset sendemail.confirm &&
474         test_confirm --suppress-cc=all --compose
475         ret="$?"
476         git config sendemail.confirm ${CONFIRM:-never}
477         test $ret = "0"
478 '
479
480 test_expect_success 'confirm detects EOF (inform assumes y)' '
481         CONFIRM=$(git config --get sendemail.confirm) &&
482         git config --unset sendemail.confirm &&
483         rm -fr outdir &&
484         git format-patch -2 -o outdir &&
485         GIT_SEND_EMAIL_NOTTY=1 \
486                 git send-email \
487                         --from="Example <nobody@example.com>" \
488                         --to=nobody@example.com \
489                         --smtp-server="$(pwd)/fake.sendmail" \
490                         outdir/*.patch < /dev/null
491         ret="$?"
492         git config sendemail.confirm ${CONFIRM:-never}
493         test $ret = "0"
494 '
495
496 test_expect_success 'confirm detects EOF (auto causes failure)' '
497         CONFIRM=$(git config --get sendemail.confirm) &&
498         git config sendemail.confirm auto &&
499         GIT_SEND_EMAIL_NOTTY=1 &&
500         export GIT_SEND_EMAIL_NOTTY &&
501                 test_must_fail git send-email \
502                         --from="Example <nobody@example.com>" \
503                         --to=nobody@example.com \
504                         --smtp-server="$(pwd)/fake.sendmail" \
505                         $patches < /dev/null
506         ret="$?"
507         git config sendemail.confirm ${CONFIRM:-never}
508         test $ret = "0"
509 '
510
511 test_expect_success 'confirm doesnt loop forever' '
512         CONFIRM=$(git config --get sendemail.confirm) &&
513         git config sendemail.confirm auto &&
514         GIT_SEND_EMAIL_NOTTY=1 &&
515         export GIT_SEND_EMAIL_NOTTY &&
516                 yes "bogus" | test_must_fail git send-email \
517                         --from="Example <nobody@example.com>" \
518                         --to=nobody@example.com \
519                         --smtp-server="$(pwd)/fake.sendmail" \
520                         $patches
521         ret="$?"
522         git config sendemail.confirm ${CONFIRM:-never}
523         test $ret = "0"
524 '
525
526 test_expect_success 'utf8 Cc is rfc2047 encoded' '
527         clean_fake_sendmail &&
528         rm -fr outdir &&
529         git format-patch -1 -o outdir --cc="àéìöú <utf8@example.com>" &&
530         git send-email \
531         --from="Example <nobody@example.com>" \
532         --to=nobody@example.com \
533         --smtp-server="$(pwd)/fake.sendmail" \
534         outdir/*.patch &&
535         grep "^Cc:" msgtxt1 |
536         grep "=?utf-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
537 '
538
539 test_expect_success '--compose adds MIME for utf8 body' '
540         clean_fake_sendmail &&
541         (echo "#!$SHELL_PATH" &&
542          echo "echo utf8 body: àéìöú >>\"\$1\""
543         ) >fake-editor-utf8 &&
544         chmod +x fake-editor-utf8 &&
545           GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
546           git send-email \
547           --compose --subject foo \
548           --from="Example <nobody@example.com>" \
549           --to=nobody@example.com \
550           --smtp-server="$(pwd)/fake.sendmail" \
551           $patches &&
552         grep "^utf8 body" msgtxt1 &&
553         grep "^Content-Type: text/plain; charset=utf-8" msgtxt1
554 '
555
556 test_expect_success '--compose respects user mime type' '
557         clean_fake_sendmail &&
558         (echo "#!$SHELL_PATH" &&
559          echo "(echo MIME-Version: 1.0"
560          echo " echo Content-Type: text/plain\\; charset=iso-8859-1"
561          echo " echo Content-Transfer-Encoding: 8bit"
562          echo " echo Subject: foo"
563          echo " echo "
564          echo " echo utf8 body: àéìöú) >\"\$1\""
565         ) >fake-editor-utf8-mime &&
566         chmod +x fake-editor-utf8-mime &&
567           GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
568           git send-email \
569           --compose --subject foo \
570           --from="Example <nobody@example.com>" \
571           --to=nobody@example.com \
572           --smtp-server="$(pwd)/fake.sendmail" \
573           $patches &&
574         grep "^utf8 body" msgtxt1 &&
575         grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 &&
576         ! grep "^Content-Type: text/plain; charset=utf-8" msgtxt1
577 '
578
579 test_expect_success '--compose adds MIME for utf8 subject' '
580         clean_fake_sendmail &&
581           GIT_EDITOR="\"$(pwd)/fake-editor\"" \
582           git send-email \
583           --compose --subject utf8-sübjëct \
584           --from="Example <nobody@example.com>" \
585           --to=nobody@example.com \
586           --smtp-server="$(pwd)/fake.sendmail" \
587           $patches &&
588         grep "^fake edit" msgtxt1 &&
589         grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
590 '
591
592 test_expect_success 'detects ambiguous reference/file conflict' '
593         echo master > master &&
594         git add master &&
595         git commit -m"add master" &&
596         test_must_fail git send-email --dry-run master 2>errors &&
597         grep disambiguate errors
598 '
599
600 test_expect_success 'feed two files' '
601         rm -fr outdir &&
602         git format-patch -2 -o outdir &&
603         git send-email \
604         --dry-run \
605         --from="Example <nobody@example.com>" \
606         --to=nobody@example.com \
607         outdir/000?-*.patch 2>errors >out &&
608         grep "^Subject: " out >subjects &&
609         test "z$(sed -n -e 1p subjects)" = "zSubject: [PATCH 1/2] Second." &&
610         test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add master"
611 '
612
613 test_expect_success 'in-reply-to but no threading' '
614         git send-email \
615                 --dry-run \
616                 --from="Example <nobody@example.com>" \
617                 --to=nobody@example.com \
618                 --in-reply-to="<in-reply-id@example.com>" \
619                 --nothread \
620                 $patches |
621         grep "In-Reply-To: <in-reply-id@example.com>"
622 '
623
624 test_done