1#!/bin/sh
2
3test_description='git send-email'
4GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
5export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
6
7. ./test-lib.sh
8
9# May be altered later in the test
10PREREQ="PERL"
11
12replace_variable_fields () {
13	sed	-e "s/^\(Date:\).*/\1 DATE-STRING/" \
14		-e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
15		-e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/"
16}
17
18test_expect_success $PREREQ 'prepare reference tree' '
19	echo "1A quick brown fox jumps over the" >file &&
20	echo "lazy dog" >>file &&
21	git add file &&
22	GIT_AUTHOR_NAME="A" git commit -a -m "Initial."
23'
24
25test_expect_success $PREREQ 'Setup helper tool' '
26	write_script fake.sendmail <<-\EOF &&
27	shift
28	output=1
29	while test -f commandline$output
30	do
31		output=$(($output+1))
32	done
33	for a
34	do
35		echo "!$a!"
36	done >commandline$output
37	cat >"msgtxt$output"
38	EOF
39	git add fake.sendmail &&
40	GIT_AUTHOR_NAME="A" git commit -a -m "Second."
41'
42
43clean_fake_sendmail () {
44	rm -f commandline* msgtxt*
45}
46
47test_expect_success $PREREQ 'Extract patches' '
48	patches=$(git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1) &&
49	threaded_patches=$(git format-patch -o threaded -s --in-reply-to="format" HEAD^1)
50'
51
52# Test no confirm early to ensure remaining tests will not hang
53test_no_confirm () {
54	rm -f no_confirm_okay
55	echo n | \
56		GIT_SEND_EMAIL_NOTTY=1 \
57		git send-email \
58		--from="Example <from@example.com>" \
59		--to=nobody@example.com \
60		--smtp-server="$(pwd)/fake.sendmail" \
61		$@ \
62		$patches >stdout &&
63		! grep "Send this email" stdout &&
64		>no_confirm_okay
65}
66
67# Exit immediately to prevent hang if a no-confirm test fails
68check_no_confirm () {
69	if ! test -f no_confirm_okay
70	then
71		say 'confirm test failed; skipping remaining tests to prevent hanging'
72		PREREQ="$PREREQ,CHECK_NO_CONFIRM"
73	fi
74	return 0
75}
76
77test_expect_success $PREREQ 'No confirm with --suppress-cc' '
78	test_no_confirm --suppress-cc=sob &&
79	check_no_confirm
80'
81
82
83test_expect_success $PREREQ 'No confirm with --confirm=never' '
84	test_no_confirm --confirm=never &&
85	check_no_confirm
86'
87
88# leave sendemail.confirm set to never after this so that none of the
89# remaining tests prompt unintentionally.
90test_expect_success $PREREQ 'No confirm with sendemail.confirm=never' '
91	git config sendemail.confirm never &&
92	test_no_confirm --compose --subject=foo &&
93	check_no_confirm
94'
95
96test_expect_success $PREREQ 'Send patches' '
97	git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
98'
99
100test_expect_success $PREREQ 'setup expect' '
101	cat >expected <<-\EOF
102	!nobody@example.com!
103	!author@example.com!
104	!one@example.com!
105	!two@example.com!
106	EOF
107'
108
109test_expect_success $PREREQ 'Verify commandline' '
110	test_cmp expected commandline1
111'
112
113test_expect_success $PREREQ 'Send patches with --envelope-sender' '
114	clean_fake_sendmail &&
115	git send-email --envelope-sender="Patch Contributor <patch@example.com>" --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
116'
117
118test_expect_success $PREREQ 'setup expect' '
119	cat >expected <<-\EOF
120	!patch@example.com!
121	!-i!
122	!nobody@example.com!
123	!author@example.com!
124	!one@example.com!
125	!two@example.com!
126	EOF
127'
128
129test_expect_success $PREREQ 'Verify commandline' '
130	test_cmp expected commandline1
131'
132
133test_expect_success $PREREQ 'Send patches with --envelope-sender=auto' '
134	clean_fake_sendmail &&
135	git send-email --envelope-sender=auto --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
136'
137
138test_expect_success $PREREQ 'setup expect' '
139	cat >expected <<-\EOF
140	!nobody@example.com!
141	!-i!
142	!nobody@example.com!
143	!author@example.com!
144	!one@example.com!
145	!two@example.com!
146	EOF
147'
148
149test_expect_success $PREREQ 'Verify commandline' '
150	test_cmp expected commandline1
151'
152
153test_expect_success $PREREQ 'setup expect for cc trailer' "
154cat >expected-cc <<\EOF
155!recipient@example.com!
156!author@example.com!
157!one@example.com!
158!two@example.com!
159!three@example.com!
160!four@example.com!
161!five@example.com!
162!six@example.com!
163EOF
164"
165
166test_expect_success $PREREQ 'cc trailer with various syntax' '
167	test_commit cc-trailer &&
168	test_when_finished "git reset --hard HEAD^" &&
169	git commit --amend -F - <<-EOF &&
170	Test Cc: trailers.
171
172	Cc: one@example.com
173	Cc: <two@example.com> # trailing comments are ignored
174	Cc: <three@example.com>, <not.four@example.com> one address per line
175	Cc: "Some # Body" <four@example.com> [ <also.a.comment> ]
176	Cc: five@example.com # not.six@example.com
177	Cc: six@example.com, not.seven@example.com
178	EOF
179	clean_fake_sendmail &&
180	git send-email -1 --to=recipient@example.com \
181		--smtp-server="$(pwd)/fake.sendmail" &&
182	test_cmp expected-cc commandline1
183'
184
185test_expect_success $PREREQ 'setup fake get_maintainer.pl script for cc trailer' "
186	write_script expected-cc-script.sh <<-EOF
187	echo 'One Person <one@example.com> (supporter:THIS (FOO/bar))'
188	echo 'Two Person <two@example.com> (maintainer:THIS THING)'
189	echo 'Third List <three@example.com> (moderated list:THIS THING (FOO/bar))'
190	echo '<four@example.com> (moderated list:FOR THING)'
191	echo 'five@example.com (open list:FOR THING (FOO/bar))'
192	echo 'six@example.com (open list)'
193	EOF
194"
195
196test_expect_success $PREREQ 'cc trailer with get_maintainer.pl output' '
197	clean_fake_sendmail &&
198	git send-email -1 --to=recipient@example.com \
199		--cc-cmd=./expected-cc-script.sh \
200		--smtp-server="$(pwd)/fake.sendmail" &&
201	test_cmp expected-cc commandline1
202'
203
204test_expect_success $PREREQ 'setup expect' "
205cat >expected-show-all-headers <<\EOF
2060001-Second.patch
207(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
208(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
209(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
210Dry-OK. Log says:
211Server: relay.example.com
212MAIL FROM:<from@example.com>
213RCPT TO:<to@example.com>
214RCPT TO:<cc@example.com>
215RCPT TO:<author@example.com>
216RCPT TO:<one@example.com>
217RCPT TO:<two@example.com>
218RCPT TO:<bcc@example.com>
219From: Example <from@example.com>
220To: to@example.com
221Cc: cc@example.com,
222	A <author@example.com>,
223	One <one@example.com>,
224	two@example.com
225Subject: [PATCH 1/1] Second.
226Date: DATE-STRING
227Message-Id: MESSAGE-ID-STRING
228X-Mailer: X-MAILER-STRING
229In-Reply-To: <unique-message-id@example.com>
230References: <unique-message-id@example.com>
231Reply-To: Reply <reply@example.com>
232MIME-Version: 1.0
233Content-Transfer-Encoding: 8bit
234
235Result: OK
236EOF
237"
238
239test_suppress_self () {
240	test_commit $3 &&
241	test_when_finished "git reset --hard HEAD^" &&
242
243	write_script cccmd-sed <<-EOF &&
244		sed -n -e s/^cccmd--//p "\$1"
245	EOF
246
247	git commit --amend --author="$1 <$2>" -F - &&
248	clean_fake_sendmail &&
249	git format-patch --stdout -1 >"suppress-self-$3.patch" &&
250
251	git send-email --from="$1 <$2>" \
252		--to=nobody@example.com \
253		--cc-cmd=./cccmd-sed \
254		--suppress-cc=self \
255		--smtp-server="$(pwd)/fake.sendmail" \
256		suppress-self-$3.patch &&
257
258	mv msgtxt1 msgtxt1-$3 &&
259	sed -e '/^$/q' msgtxt1-$3 >"msghdr1-$3" &&
260
261	(grep '^Cc:' msghdr1-$3 >"actual-no-cc-$3";
262	 test_must_be_empty actual-no-cc-$3)
263}
264
265test_suppress_self_unquoted () {
266	test_suppress_self "$1" "$2" "unquoted-$3" <<-EOF
267		test suppress-cc.self unquoted-$3 with name $1 email $2
268
269		unquoted-$3
270
271		cccmd--$1 <$2>
272
273		Cc: $1 <$2>
274		Signed-off-by: $1 <$2>
275	EOF
276}
277
278test_suppress_self_quoted () {
279	test_suppress_self "$1" "$2" "quoted-$3" <<-EOF
280		test suppress-cc.self quoted-$3 with name $1 email $2
281
282		quoted-$3
283
284		cccmd--"$1" <$2>
285
286		Cc: $1 <$2>
287		Cc: "$1" <$2>
288		Signed-off-by: $1 <$2>
289		Signed-off-by: "$1" <$2>
290	EOF
291}
292
293test_expect_success $PREREQ 'self name is suppressed' "
294	test_suppress_self_unquoted 'A U Thor' 'author@example.com' \
295		'self_name_suppressed'
296"
297
298test_expect_success $PREREQ 'self name with dot is suppressed' "
299	test_suppress_self_quoted 'A U. Thor' 'author@example.com' \
300		'self_name_dot_suppressed'
301"
302
303test_expect_success $PREREQ 'non-ascii self name is suppressed' "
304	test_suppress_self_quoted 'Füñný Nâmé' 'odd_?=mail@example.com' \
305		'non_ascii_self_suppressed'
306"
307
308# This name is long enough to force format-patch to split it into multiple
309# encoded-words, assuming it uses UTF-8 with the "Q" encoding.
310test_expect_success $PREREQ 'long non-ascii self name is suppressed' "
311	test_suppress_self_quoted 'Ƒüñníęř €. Nâṁé' 'odd_?=mail@example.com' \
312		'long_non_ascii_self_suppressed'
313"
314
315test_expect_success $PREREQ 'sanitized self name is suppressed' "
316	test_suppress_self_unquoted '\"A U. Thor\"' 'author@example.com' \
317		'self_name_sanitized_suppressed'
318"
319
320test_expect_success $PREREQ 'Show all headers' '
321	git send-email \
322		--dry-run \
323		--suppress-cc=sob \
324		--from="Example <from@example.com>" \
325		--reply-to="Reply <reply@example.com>" \
326		--to=to@example.com \
327		--cc=cc@example.com \
328		--bcc=bcc@example.com \
329		--in-reply-to="<unique-message-id@example.com>" \
330		--smtp-server relay.example.com \
331		$patches | replace_variable_fields \
332		>actual-show-all-headers &&
333	test_cmp expected-show-all-headers actual-show-all-headers
334'
335
336test_expect_success $PREREQ 'Prompting works' '
337	clean_fake_sendmail &&
338	(echo "to@example.com" &&
339	 echo ""
340	) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
341		--smtp-server="$(pwd)/fake.sendmail" \
342		$patches \
343		2>errors &&
344		grep "^From: A U Thor <author@example.com>\$" msgtxt1 &&
345		grep "^To: to@example.com\$" msgtxt1
346'
347
348test_expect_success $PREREQ,AUTOIDENT 'implicit ident is allowed' '
349	clean_fake_sendmail &&
350	(sane_unset GIT_AUTHOR_NAME &&
351	sane_unset GIT_AUTHOR_EMAIL &&
352	sane_unset GIT_COMMITTER_NAME &&
353	sane_unset GIT_COMMITTER_EMAIL &&
354	GIT_SEND_EMAIL_NOTTY=1 git send-email \
355		--smtp-server="$(pwd)/fake.sendmail" \
356		--to=to@example.com \
357		$patches </dev/null 2>errors
358	)
359'
360
361test_expect_success $PREREQ,!AUTOIDENT 'broken implicit ident aborts send-email' '
362	clean_fake_sendmail &&
363	(sane_unset GIT_AUTHOR_NAME &&
364	sane_unset GIT_AUTHOR_EMAIL &&
365	sane_unset GIT_COMMITTER_NAME &&
366	sane_unset GIT_COMMITTER_EMAIL &&
367	GIT_SEND_EMAIL_NOTTY=1 && export GIT_SEND_EMAIL_NOTTY &&
368	test_must_fail git send-email \
369		--smtp-server="$(pwd)/fake.sendmail" \
370		--to=to@example.com \
371		$patches </dev/null 2>errors &&
372	test_i18ngrep "tell me who you are" errors
373	)
374'
375
376test_expect_success $PREREQ 'setup tocmd and cccmd scripts' '
377	write_script tocmd-sed <<-\EOF &&
378	sed -n -e "s/^tocmd--//p" "$1"
379	EOF
380	write_script cccmd-sed <<-\EOF
381	sed -n -e "s/^cccmd--//p" "$1"
382	EOF
383'
384
385test_expect_success $PREREQ 'tocmd works' '
386	clean_fake_sendmail &&
387	cp $patches tocmd.patch &&
388	echo tocmd--tocmd@example.com >>tocmd.patch &&
389	git send-email \
390		--from="Example <nobody@example.com>" \
391		--to-cmd=./tocmd-sed \
392		--smtp-server="$(pwd)/fake.sendmail" \
393		tocmd.patch \
394		&&
395	grep "^To: tocmd@example.com" msgtxt1
396'
397
398test_expect_success $PREREQ 'cccmd works' '
399	clean_fake_sendmail &&
400	cp $patches cccmd.patch &&
401	echo "cccmd--  cccmd@example.com" >>cccmd.patch &&
402	git send-email \
403		--from="Example <nobody@example.com>" \
404		--to=nobody@example.com \
405		--cc-cmd=./cccmd-sed \
406		--smtp-server="$(pwd)/fake.sendmail" \
407		cccmd.patch \
408		&&
409	grep "^	cccmd@example.com" msgtxt1
410'
411
412test_expect_success $PREREQ 'reject long lines' '
413	z8=zzzzzzzz &&
414	z64=$z8$z8$z8$z8$z8$z8$z8$z8 &&
415	z512=$z64$z64$z64$z64$z64$z64$z64$z64 &&
416	clean_fake_sendmail &&
417	cp $patches longline.patch &&
418	cat >>longline.patch <<-EOF &&
419	$z512$z512
420	not a long line
421	$z512$z512
422	EOF
423	test_must_fail git send-email \
424		--from="Example <nobody@example.com>" \
425		--to=nobody@example.com \
426		--smtp-server="$(pwd)/fake.sendmail" \
427		--transfer-encoding=8bit \
428		$patches longline.patch \
429		2>actual &&
430	cat >expect <<-\EOF &&
431	fatal: longline.patch:35 is longer than 998 characters
432	warning: no patches were sent
433	EOF
434	test_cmp expect actual
435'
436
437test_expect_success $PREREQ 'no patch was sent' '
438	! test -e commandline1
439'
440
441test_expect_success $PREREQ 'Author From: in message body' '
442	clean_fake_sendmail &&
443	git send-email \
444		--from="Example <nobody@example.com>" \
445		--to=nobody@example.com \
446		--smtp-server="$(pwd)/fake.sendmail" \
447		$patches &&
448	sed "1,/^\$/d" <msgtxt1 >msgbody1 &&
449	grep "From: A <author@example.com>" msgbody1
450'
451
452test_expect_success $PREREQ 'Author From: not in message body' '
453	clean_fake_sendmail &&
454	git send-email \
455		--from="A <author@example.com>" \
456		--to=nobody@example.com \
457		--smtp-server="$(pwd)/fake.sendmail" \
458		$patches &&
459	sed "1,/^\$/d" <msgtxt1 >msgbody1 &&
460	! grep "From: A <author@example.com>" msgbody1
461'
462
463test_expect_success $PREREQ 'allow long lines with --no-validate' '
464	git send-email \
465		--from="Example <nobody@example.com>" \
466		--to=nobody@example.com \
467		--smtp-server="$(pwd)/fake.sendmail" \
468		--no-validate \
469		$patches longline.patch \
470		2>errors
471'
472
473test_expect_success $PREREQ 'short lines with auto encoding are 8bit' '
474	clean_fake_sendmail &&
475	git send-email \
476		--from="A <author@example.com>" \
477		--to=nobody@example.com \
478		--smtp-server="$(pwd)/fake.sendmail" \
479		--transfer-encoding=auto \
480		$patches &&
481	grep "Content-Transfer-Encoding: 8bit" msgtxt1
482'
483
484test_expect_success $PREREQ 'long lines with auto encoding are quoted-printable' '
485	clean_fake_sendmail &&
486	git send-email \
487		--from="Example <nobody@example.com>" \
488		--to=nobody@example.com \
489		--smtp-server="$(pwd)/fake.sendmail" \
490		--transfer-encoding=auto \
491		--no-validate \
492		longline.patch &&
493	grep "Content-Transfer-Encoding: quoted-printable" msgtxt1
494'
495
496test_expect_success $PREREQ 'carriage returns with auto encoding are quoted-printable' '
497	clean_fake_sendmail &&
498	cp $patches cr.patch &&
499	printf "this is a line\r\n" >>cr.patch &&
500	git send-email \
501		--from="Example <nobody@example.com>" \
502		--to=nobody@example.com \
503		--smtp-server="$(pwd)/fake.sendmail" \
504		--transfer-encoding=auto \
505		--no-validate \
506		cr.patch &&
507	grep "Content-Transfer-Encoding: quoted-printable" msgtxt1
508'
509
510for enc in auto quoted-printable base64
511do
512	test_expect_success $PREREQ "--validate passes with encoding $enc" '
513		git send-email \
514			--from="Example <nobody@example.com>" \
515			--to=nobody@example.com \
516			--smtp-server="$(pwd)/fake.sendmail" \
517			--transfer-encoding=$enc \
518			--validate \
519			$patches longline.patch
520	'
521
522done
523
524test_expect_success $PREREQ "--validate respects relative core.hooksPath path" '
525	clean_fake_sendmail &&
526	mkdir my-hooks &&
527	test_when_finished "rm my-hooks.ran" &&
528	write_script my-hooks/sendemail-validate <<-\EOF &&
529	>my-hooks.ran
530	exit 1
531	EOF
532	test_config core.hooksPath "my-hooks" &&
533	test_must_fail git send-email \
534		--from="Example <nobody@example.com>" \
535		--to=nobody@example.com \
536		--smtp-server="$(pwd)/fake.sendmail" \
537		--validate \
538		longline.patch 2>actual &&
539	test_path_is_file my-hooks.ran &&
540	cat >expect <<-EOF &&
541	fatal: longline.patch: rejected by sendemail-validate hook
542	fatal: command '"'"'my-hooks/sendemail-validate'"'"' died with exit code 1
543	warning: no patches were sent
544	EOF
545	test_cmp expect actual
546'
547
548test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" '
549	hooks_path="$(pwd)/my-hooks" &&
550	test_config core.hooksPath "$hooks_path" &&
551	test_when_finished "rm my-hooks.ran" &&
552	test_must_fail git send-email \
553		--from="Example <nobody@example.com>" \
554		--to=nobody@example.com \
555		--smtp-server="$(pwd)/fake.sendmail" \
556		--validate \
557		longline.patch 2>actual &&
558	test_path_is_file my-hooks.ran &&
559	cat >expect <<-EOF &&
560	fatal: longline.patch: rejected by sendemail-validate hook
561	fatal: command '"'"'$hooks_path/sendemail-validate'"'"' died with exit code 1
562	warning: no patches were sent
563	EOF
564	test_cmp expect actual
565'
566
567for enc in 7bit 8bit quoted-printable base64
568do
569	test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" '
570		clean_fake_sendmail &&
571		git send-email \
572			--from="Example <nobody@example.com>" \
573			--to=nobody@example.com \
574			--smtp-server="$(pwd)/fake.sendmail" \
575			--transfer-encoding=$enc \
576			$patches &&
577		grep "Content-Transfer-Encoding: $enc" msgtxt1
578	'
579done
580
581test_expect_success $PREREQ 'Invalid In-Reply-To' '
582	clean_fake_sendmail &&
583	git send-email \
584		--from="Example <nobody@example.com>" \
585		--to=nobody@example.com \
586		--in-reply-to=" " \
587		--smtp-server="$(pwd)/fake.sendmail" \
588		$patches \
589		2>errors &&
590	! grep "^In-Reply-To: < *>" msgtxt1
591'
592
593test_expect_success $PREREQ 'Valid In-Reply-To when prompting' '
594	clean_fake_sendmail &&
595	(echo "From Example <from@example.com>" &&
596	 echo "To Example <to@example.com>" &&
597	 echo ""
598	) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
599		--smtp-server="$(pwd)/fake.sendmail" \
600		$patches 2>errors &&
601	! grep "^In-Reply-To: < *>" msgtxt1
602'
603
604test_expect_success $PREREQ 'In-Reply-To without --chain-reply-to' '
605	clean_fake_sendmail &&
606	echo "<unique-message-id@example.com>" >expect &&
607	git send-email \
608		--from="Example <nobody@example.com>" \
609		--to=nobody@example.com \
610		--no-chain-reply-to \
611		--in-reply-to="$(cat expect)" \
612		--smtp-server="$(pwd)/fake.sendmail" \
613		$patches $patches $patches \
614		2>errors &&
615	# The first message is a reply to --in-reply-to
616	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual &&
617	test_cmp expect actual &&
618	# Second and subsequent messages are replies to the first one
619	sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt1 >expect &&
620	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt2 >actual &&
621	test_cmp expect actual &&
622	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt3 >actual &&
623	test_cmp expect actual
624'
625
626test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' '
627	clean_fake_sendmail &&
628	echo "<unique-message-id@example.com>" >expect &&
629	git send-email \
630		--from="Example <nobody@example.com>" \
631		--to=nobody@example.com \
632		--chain-reply-to \
633		--in-reply-to="$(cat expect)" \
634		--smtp-server="$(pwd)/fake.sendmail" \
635		$patches $patches $patches \
636		2>errors &&
637	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual &&
638	test_cmp expect actual &&
639	sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt1 >expect &&
640	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt2 >actual &&
641	test_cmp expect actual &&
642	sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt2 >expect &&
643	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt3 >actual &&
644	test_cmp expect actual
645'
646
647test_set_editor "$(pwd)/fake-editor"
648
649test_expect_success $PREREQ 'setup erroring fake editor' '
650	write_script fake-editor <<-\EOF
651	echo >&2 "I am about to error"
652	exit 1
653	EOF
654'
655
656test_expect_success $PREREQ 'fake editor dies with error' '
657	clean_fake_sendmail &&
658	test_must_fail git send-email \
659		--compose --subject foo \
660		--from="Example <nobody@example.com>" \
661		--to=nobody@example.com \
662		--smtp-server="$(pwd)/fake.sendmail" \
663		$patches 2>err &&
664	grep "I am about to error" err &&
665	grep "the editor exited uncleanly, aborting everything" err
666'
667
668test_expect_success $PREREQ 'setup fake editor' '
669	write_script fake-editor <<-\EOF
670	echo fake edit >>"$1"
671	EOF
672'
673
674test_expect_success $PREREQ '--compose works' '
675	clean_fake_sendmail &&
676	git send-email \
677	--compose --subject foo \
678	--from="Example <nobody@example.com>" \
679	--to=nobody@example.com \
680	--smtp-server="$(pwd)/fake.sendmail" \
681	$patches \
682	2>errors
683'
684
685test_expect_success $PREREQ 'first message is compose text' '
686	grep "^fake edit" msgtxt1
687'
688
689test_expect_success $PREREQ 'second message is patch' '
690	grep "Subject:.*Second" msgtxt2
691'
692
693test_expect_success $PREREQ 'setup expect' "
694cat >expected-suppress-sob <<\EOF
6950001-Second.patch
696(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
697(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
698(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
699Dry-OK. Log says:
700Server: relay.example.com
701MAIL FROM:<from@example.com>
702RCPT TO:<to@example.com>
703RCPT TO:<cc@example.com>
704RCPT TO:<author@example.com>
705RCPT TO:<one@example.com>
706RCPT TO:<two@example.com>
707From: Example <from@example.com>
708To: to@example.com
709Cc: cc@example.com,
710	A <author@example.com>,
711	One <one@example.com>,
712	two@example.com
713Subject: [PATCH 1/1] Second.
714Date: DATE-STRING
715Message-Id: MESSAGE-ID-STRING
716X-Mailer: X-MAILER-STRING
717MIME-Version: 1.0
718Content-Transfer-Encoding: 8bit
719
720Result: OK
721EOF
722"
723
724test_suppression () {
725	git send-email \
726		--dry-run \
727		--suppress-cc=$1 ${2+"--suppress-cc=$2"} \
728		--from="Example <from@example.com>" \
729		--to=to@example.com \
730		--smtp-server relay.example.com \
731		$patches | replace_variable_fields \
732		>actual-suppress-$1${2+"-$2"} &&
733	test_cmp expected-suppress-$1${2+"-$2"} actual-suppress-$1${2+"-$2"}
734}
735
736test_expect_success $PREREQ 'sendemail.cc set' '
737	git config sendemail.cc cc@example.com &&
738	test_suppression sob
739'
740
741test_expect_success $PREREQ 'setup expect' "
742cat >expected-suppress-sob <<\EOF
7430001-Second.patch
744(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
745(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
746(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
747Dry-OK. Log says:
748Server: relay.example.com
749MAIL FROM:<from@example.com>
750RCPT TO:<to@example.com>
751RCPT TO:<author@example.com>
752RCPT TO:<one@example.com>
753RCPT TO:<two@example.com>
754From: Example <from@example.com>
755To: to@example.com
756Cc: A <author@example.com>,
757	One <one@example.com>,
758	two@example.com
759Subject: [PATCH 1/1] Second.
760Date: DATE-STRING
761Message-Id: MESSAGE-ID-STRING
762X-Mailer: X-MAILER-STRING
763MIME-Version: 1.0
764Content-Transfer-Encoding: 8bit
765
766Result: OK
767EOF
768"
769
770test_expect_success $PREREQ 'sendemail.cc unset' '
771	git config --unset sendemail.cc &&
772	test_suppression sob
773'
774
775test_expect_success $PREREQ 'setup expect' "
776cat >expected-suppress-cccmd <<\EOF
7770001-Second.patch
778(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
779(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
780(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
781(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
782Dry-OK. Log says:
783Server: relay.example.com
784MAIL FROM:<from@example.com>
785RCPT TO:<to@example.com>
786RCPT TO:<author@example.com>
787RCPT TO:<one@example.com>
788RCPT TO:<two@example.com>
789RCPT TO:<committer@example.com>
790From: Example <from@example.com>
791To: to@example.com
792Cc: A <author@example.com>,
793	One <one@example.com>,
794	two@example.com,
795	C O Mitter <committer@example.com>
796Subject: [PATCH 1/1] Second.
797Date: DATE-STRING
798Message-Id: MESSAGE-ID-STRING
799X-Mailer: X-MAILER-STRING
800MIME-Version: 1.0
801Content-Transfer-Encoding: 8bit
802
803Result: OK
804EOF
805"
806
807test_expect_success $PREREQ 'sendemail.cccmd' '
808	write_script cccmd <<-\EOF &&
809	echo cc-cmd@example.com
810	EOF
811	git config sendemail.cccmd ./cccmd &&
812	test_suppression cccmd
813'
814
815test_expect_success $PREREQ 'setup expect' '
816cat >expected-suppress-all <<\EOF
8170001-Second.patch
818Dry-OK. Log says:
819Server: relay.example.com
820MAIL FROM:<from@example.com>
821RCPT TO:<to@example.com>
822From: Example <from@example.com>
823To: to@example.com
824Subject: [PATCH 1/1] Second.
825Date: DATE-STRING
826Message-Id: MESSAGE-ID-STRING
827X-Mailer: X-MAILER-STRING
828MIME-Version: 1.0
829Content-Transfer-Encoding: 8bit
830
831Result: OK
832EOF
833'
834
835test_expect_success $PREREQ '--suppress-cc=all' '
836	test_suppression all
837'
838
839test_expect_success $PREREQ 'setup expect' "
840cat >expected-suppress-body <<\EOF
8410001-Second.patch
842(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
843(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
844(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
845(cc-cmd) Adding cc: cc-cmd@example.com from: './cccmd'
846Dry-OK. Log says:
847Server: relay.example.com
848MAIL FROM:<from@example.com>
849RCPT TO:<to@example.com>
850RCPT TO:<author@example.com>
851RCPT TO:<one@example.com>
852RCPT TO:<two@example.com>
853RCPT TO:<cc-cmd@example.com>
854From: Example <from@example.com>
855To: to@example.com
856Cc: A <author@example.com>,
857	One <one@example.com>,
858	two@example.com,
859	cc-cmd@example.com
860Subject: [PATCH 1/1] Second.
861Date: DATE-STRING
862Message-Id: MESSAGE-ID-STRING
863X-Mailer: X-MAILER-STRING
864MIME-Version: 1.0
865Content-Transfer-Encoding: 8bit
866
867Result: OK
868EOF
869"
870
871test_expect_success $PREREQ '--suppress-cc=body' '
872	test_suppression body
873'
874
875test_expect_success $PREREQ 'setup expect' "
876cat >expected-suppress-body-cccmd <<\EOF
8770001-Second.patch
878(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
879(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
880(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
881Dry-OK. Log says:
882Server: relay.example.com
883MAIL FROM:<from@example.com>
884RCPT TO:<to@example.com>
885RCPT TO:<author@example.com>
886RCPT TO:<one@example.com>
887RCPT TO:<two@example.com>
888From: Example <from@example.com>
889To: to@example.com
890Cc: A <author@example.com>,
891	One <one@example.com>,
892	two@example.com
893Subject: [PATCH 1/1] Second.
894Date: DATE-STRING
895Message-Id: MESSAGE-ID-STRING
896X-Mailer: X-MAILER-STRING
897MIME-Version: 1.0
898Content-Transfer-Encoding: 8bit
899
900Result: OK
901EOF
902"
903
904test_expect_success $PREREQ '--suppress-cc=body --suppress-cc=cccmd' '
905	test_suppression body cccmd
906'
907
908test_expect_success $PREREQ 'setup expect' "
909cat >expected-suppress-sob <<\EOF
9100001-Second.patch
911(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
912(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
913(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
914Dry-OK. Log says:
915Server: relay.example.com
916MAIL FROM:<from@example.com>
917RCPT TO:<to@example.com>
918RCPT TO:<author@example.com>
919RCPT TO:<one@example.com>
920RCPT TO:<two@example.com>
921From: Example <from@example.com>
922To: to@example.com
923Cc: A <author@example.com>,
924	One <one@example.com>,
925	two@example.com
926Subject: [PATCH 1/1] Second.
927Date: DATE-STRING
928Message-Id: MESSAGE-ID-STRING
929X-Mailer: X-MAILER-STRING
930MIME-Version: 1.0
931Content-Transfer-Encoding: 8bit
932
933Result: OK
934EOF
935"
936
937test_expect_success $PREREQ '--suppress-cc=sob' '
938	test_might_fail git config --unset sendemail.cccmd &&
939	test_suppression sob
940'
941
942test_expect_success $PREREQ 'setup expect' "
943cat >expected-suppress-bodycc <<\EOF
9440001-Second.patch
945(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
946(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
947(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
948(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
949Dry-OK. Log says:
950Server: relay.example.com
951MAIL FROM:<from@example.com>
952RCPT TO:<to@example.com>
953RCPT TO:<author@example.com>
954RCPT TO:<one@example.com>
955RCPT TO:<two@example.com>
956RCPT TO:<committer@example.com>
957From: Example <from@example.com>
958To: to@example.com
959Cc: A <author@example.com>,
960	One <one@example.com>,
961	two@example.com,
962	C O Mitter <committer@example.com>
963Subject: [PATCH 1/1] Second.
964Date: DATE-STRING
965Message-Id: MESSAGE-ID-STRING
966X-Mailer: X-MAILER-STRING
967MIME-Version: 1.0
968Content-Transfer-Encoding: 8bit
969
970Result: OK
971EOF
972"
973
974test_expect_success $PREREQ '--suppress-cc=bodycc' '
975	test_suppression bodycc
976'
977
978test_expect_success $PREREQ 'setup expect' "
979cat >expected-suppress-cc <<\EOF
9800001-Second.patch
981(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
982(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
983Dry-OK. Log says:
984Server: relay.example.com
985MAIL FROM:<from@example.com>
986RCPT TO:<to@example.com>
987RCPT TO:<author@example.com>
988RCPT TO:<committer@example.com>
989From: Example <from@example.com>
990To: to@example.com
991Cc: A <author@example.com>,
992	C O Mitter <committer@example.com>
993Subject: [PATCH 1/1] Second.
994Date: DATE-STRING
995Message-Id: MESSAGE-ID-STRING
996X-Mailer: X-MAILER-STRING
997MIME-Version: 1.0
998Content-Transfer-Encoding: 8bit
999
1000Result: OK
1001EOF
1002"
1003
1004test_expect_success $PREREQ '--suppress-cc=cc' '
1005	test_suppression cc
1006'
1007
1008test_confirm () {
1009	echo y | \
1010		GIT_SEND_EMAIL_NOTTY=1 \
1011		git send-email \
1012		--from="Example <nobody@example.com>" \
1013		--to=nobody@example.com \
1014		--smtp-server="$(pwd)/fake.sendmail" \
1015		$@ $patches >stdout &&
1016	grep "Send this email" stdout
1017}
1018
1019test_expect_success $PREREQ '--confirm=always' '
1020	test_confirm --confirm=always --suppress-cc=all
1021'
1022
1023test_expect_success $PREREQ '--confirm=auto' '
1024	test_confirm --confirm=auto
1025'
1026
1027test_expect_success $PREREQ '--confirm=cc' '
1028	test_confirm --confirm=cc
1029'
1030
1031test_expect_success $PREREQ '--confirm=compose' '
1032	test_confirm --confirm=compose --compose
1033'
1034
1035test_expect_success $PREREQ 'confirm by default (due to cc)' '
1036	test_when_finished git config sendemail.confirm never &&
1037	git config --unset sendemail.confirm &&
1038	test_confirm
1039'
1040
1041test_expect_success $PREREQ 'confirm by default (due to --compose)' '
1042	test_when_finished git config sendemail.confirm never &&
1043	git config --unset sendemail.confirm &&
1044	test_confirm --suppress-cc=all --compose
1045'
1046
1047test_expect_success $PREREQ 'confirm detects EOF (inform assumes y)' '
1048	test_when_finished git config sendemail.confirm never &&
1049	git config --unset sendemail.confirm &&
1050	rm -fr outdir &&
1051	git format-patch -2 -o outdir &&
1052	GIT_SEND_EMAIL_NOTTY=1 \
1053		git send-email \
1054			--from="Example <nobody@example.com>" \
1055			--to=nobody@example.com \
1056			--smtp-server="$(pwd)/fake.sendmail" \
1057			outdir/*.patch </dev/null
1058'
1059
1060test_expect_success $PREREQ 'confirm detects EOF (auto causes failure)' '
1061	test_when_finished git config sendemail.confirm never &&
1062	git config sendemail.confirm auto &&
1063	GIT_SEND_EMAIL_NOTTY=1 &&
1064	export GIT_SEND_EMAIL_NOTTY &&
1065		test_must_fail git send-email \
1066			--from="Example <nobody@example.com>" \
1067			--to=nobody@example.com \
1068			--smtp-server="$(pwd)/fake.sendmail" \
1069			$patches </dev/null
1070'
1071
1072test_expect_success $PREREQ 'confirm does not loop forever' '
1073	test_when_finished git config sendemail.confirm never &&
1074	git config sendemail.confirm auto &&
1075	GIT_SEND_EMAIL_NOTTY=1 &&
1076	export GIT_SEND_EMAIL_NOTTY &&
1077		yes "bogus" | test_must_fail git send-email \
1078			--from="Example <nobody@example.com>" \
1079			--to=nobody@example.com \
1080			--smtp-server="$(pwd)/fake.sendmail" \
1081			$patches
1082'
1083
1084test_expect_success $PREREQ 'utf8 Cc is rfc2047 encoded' '
1085	clean_fake_sendmail &&
1086	rm -fr outdir &&
1087	git format-patch -1 -o outdir --cc="àéìöú <utf8@example.com>" &&
1088	git send-email \
1089	--from="Example <nobody@example.com>" \
1090	--to=nobody@example.com \
1091	--smtp-server="$(pwd)/fake.sendmail" \
1092	outdir/*.patch &&
1093	grep "^	" msgtxt1 |
1094	grep "=?UTF-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
1095'
1096
1097test_expect_success $PREREQ '--compose adds MIME for utf8 body' '
1098	clean_fake_sendmail &&
1099	write_script fake-editor-utf8 <<-\EOF &&
1100	echo "utf8 body: àéìöú" >>"$1"
1101	EOF
1102	GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
1103	git send-email \
1104		--compose --subject foo \
1105		--from="Example <nobody@example.com>" \
1106		--to=nobody@example.com \
1107		--smtp-server="$(pwd)/fake.sendmail" \
1108		$patches &&
1109	grep "^utf8 body" msgtxt1 &&
1110	grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
1111'
1112
1113test_expect_success $PREREQ '--compose respects user mime type' '
1114	clean_fake_sendmail &&
1115	write_script fake-editor-utf8-mime <<-\EOF &&
1116	cat >"$1" <<-\EOM
1117	MIME-Version: 1.0
1118	Content-Type: text/plain; charset=iso-8859-1
1119	Content-Transfer-Encoding: 8bit
1120	Subject: foo
1121
1122	utf8 body: àéìöú
1123	EOM
1124	EOF
1125	GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
1126	git send-email \
1127		--compose --subject foo \
1128		--from="Example <nobody@example.com>" \
1129		--to=nobody@example.com \
1130		--smtp-server="$(pwd)/fake.sendmail" \
1131		$patches &&
1132	grep "^utf8 body" msgtxt1 &&
1133	grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 &&
1134	! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
1135'
1136
1137test_expect_success $PREREQ '--compose adds MIME for utf8 subject' '
1138	clean_fake_sendmail &&
1139	GIT_EDITOR="\"$(pwd)/fake-editor\"" \
1140	git send-email \
1141		--compose --subject utf8-sübjëct \
1142		--from="Example <nobody@example.com>" \
1143		--to=nobody@example.com \
1144		--smtp-server="$(pwd)/fake.sendmail" \
1145		$patches &&
1146	grep "^fake edit" msgtxt1 &&
1147	grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
1148'
1149
1150test_expect_success $PREREQ 'utf8 author is correctly passed on' '
1151	clean_fake_sendmail &&
1152	test_commit weird_author &&
1153	test_when_finished "git reset --hard HEAD^" &&
1154	git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" &&
1155	git format-patch --stdout -1 >funny_name.patch &&
1156	git send-email --from="Example <nobody@example.com>" \
1157		--to=nobody@example.com \
1158		--smtp-server="$(pwd)/fake.sendmail" \
1159		funny_name.patch &&
1160	grep "^From: Füñný Nâmé <odd_?=mail@example.com>" msgtxt1
1161'
1162
1163test_expect_success $PREREQ 'utf8 sender is not duplicated' '
1164	clean_fake_sendmail &&
1165	test_commit weird_sender &&
1166	test_when_finished "git reset --hard HEAD^" &&
1167	git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" &&
1168	git format-patch --stdout -1 >funny_name.patch &&
1169	git send-email --from="Füñný Nâmé <odd_?=mail@example.com>" \
1170		--to=nobody@example.com \
1171		--smtp-server="$(pwd)/fake.sendmail" \
1172		funny_name.patch &&
1173	grep "^From: " msgtxt1 >msgfrom &&
1174	test_line_count = 1 msgfrom
1175'
1176
1177test_expect_success $PREREQ 'sendemail.composeencoding works' '
1178	clean_fake_sendmail &&
1179	git config sendemail.composeencoding iso-8859-1 &&
1180	write_script fake-editor-utf8 <<-\EOF &&
1181	echo "utf8 body: àéìöú" >>"$1"
1182	EOF
1183	GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
1184	git send-email \
1185		--compose --subject foo \
1186		--from="Example <nobody@example.com>" \
1187		--to=nobody@example.com \
1188		--smtp-server="$(pwd)/fake.sendmail" \
1189		$patches &&
1190	grep "^utf8 body" msgtxt1 &&
1191	grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1
1192'
1193
1194test_expect_success $PREREQ '--compose-encoding works' '
1195	clean_fake_sendmail &&
1196	write_script fake-editor-utf8 <<-\EOF &&
1197	echo "utf8 body: àéìöú" >>"$1"
1198	EOF
1199	GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
1200	git send-email \
1201		--compose-encoding iso-8859-1 \
1202		--compose --subject foo \
1203		--from="Example <nobody@example.com>" \
1204		--to=nobody@example.com \
1205		--smtp-server="$(pwd)/fake.sendmail" \
1206		$patches &&
1207	grep "^utf8 body" msgtxt1 &&
1208	grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1
1209'
1210
1211test_expect_success $PREREQ '--compose-encoding overrides sendemail.composeencoding' '
1212	clean_fake_sendmail &&
1213	git config sendemail.composeencoding iso-8859-1 &&
1214	write_script fake-editor-utf8 <<-\EOF &&
1215	echo "utf8 body: àéìöú" >>"$1"
1216	EOF
1217	GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
1218	git send-email \
1219		--compose-encoding iso-8859-2 \
1220		--compose --subject foo \
1221		--from="Example <nobody@example.com>" \
1222		--to=nobody@example.com \
1223		--smtp-server="$(pwd)/fake.sendmail" \
1224		$patches &&
1225	grep "^utf8 body" msgtxt1 &&
1226	grep "^Content-Type: text/plain; charset=iso-8859-2" msgtxt1
1227'
1228
1229test_expect_success $PREREQ '--compose-encoding adds correct MIME for subject' '
1230	clean_fake_sendmail &&
1231	GIT_EDITOR="\"$(pwd)/fake-editor\"" \
1232	git send-email \
1233		--compose-encoding iso-8859-2 \
1234		--compose --subject utf8-sübjëct \
1235		--from="Example <nobody@example.com>" \
1236		--to=nobody@example.com \
1237		--smtp-server="$(pwd)/fake.sendmail" \
1238		$patches &&
1239	grep "^fake edit" msgtxt1 &&
1240	grep "^Subject: =?iso-8859-2?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
1241'
1242
1243test_expect_success $PREREQ 'detects ambiguous reference/file conflict' '
1244	echo main >main &&
1245	git add main &&
1246	git commit -m"add main" &&
1247	test_must_fail git send-email --dry-run main 2>errors &&
1248	grep disambiguate errors
1249'
1250
1251test_expect_success $PREREQ 'feed two files' '
1252	rm -fr outdir &&
1253	git format-patch -2 -o outdir &&
1254	git send-email \
1255		--dry-run \
1256		--from="Example <nobody@example.com>" \
1257		--to=nobody@example.com \
1258		outdir/000?-*.patch 2>errors >out &&
1259	grep "^Subject: " out >subjects &&
1260	test "z$(sed -n -e 1p subjects)" = "zSubject: [PATCH 1/2] Second." &&
1261	test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add main"
1262'
1263
1264test_expect_success $PREREQ 'in-reply-to but no threading' '
1265	git send-email \
1266		--dry-run \
1267		--from="Example <nobody@example.com>" \
1268		--to=nobody@example.com \
1269		--in-reply-to="<in-reply-id@example.com>" \
1270		--no-thread \
1271		$patches >out &&
1272	grep "In-Reply-To: <in-reply-id@example.com>" out
1273'
1274
1275test_expect_success $PREREQ 'no in-reply-to and no threading' '
1276	git send-email \
1277		--dry-run \
1278		--from="Example <nobody@example.com>" \
1279		--to=nobody@example.com \
1280		--no-thread \
1281		$patches >stdout &&
1282	! grep "In-Reply-To: " stdout
1283'
1284
1285test_expect_success $PREREQ 'threading but no chain-reply-to' '
1286	git send-email \
1287		--dry-run \
1288		--from="Example <nobody@example.com>" \
1289		--to=nobody@example.com \
1290		--thread \
1291		--no-chain-reply-to \
1292		$patches $patches >stdout &&
1293	grep "In-Reply-To: " stdout
1294'
1295
1296test_expect_success $PREREQ 'override in-reply-to if no threading' '
1297	git send-email \
1298		--dry-run \
1299		--from="Example <nobody@example.com>" \
1300		--to=nobody@example.com \
1301		--no-thread \
1302		--in-reply-to="override" \
1303		$threaded_patches >stdout &&
1304	grep "In-Reply-To: <override>" stdout
1305'
1306
1307test_expect_success $PREREQ 'sendemail.to works' '
1308	git config --replace-all sendemail.to "Somebody <somebody@ex.com>" &&
1309	git send-email \
1310		--dry-run \
1311		--from="Example <nobody@example.com>" \
1312		$patches >stdout &&
1313	grep "To: Somebody <somebody@ex.com>" stdout
1314'
1315
1316test_expect_success $PREREQ 'setup sendemail.identity' '
1317	git config --replace-all sendemail.to "default@example.com" &&
1318	git config --replace-all sendemail.isp.to "isp@example.com" &&
1319	git config --replace-all sendemail.cloud.to "cloud@example.com"
1320'
1321
1322test_expect_success $PREREQ 'sendemail.identity: reads the correct identity config' '
1323	git -c sendemail.identity=cloud send-email \
1324		--dry-run \
1325		--from="nobody@example.com" \
1326		$patches >stdout &&
1327	grep "To: cloud@example.com" stdout
1328'
1329
1330test_expect_success $PREREQ 'sendemail.identity: identity overrides sendemail.identity' '
1331	git -c sendemail.identity=cloud send-email \
1332		--identity=isp \
1333		--dry-run \
1334		--from="nobody@example.com" \
1335		$patches >stdout &&
1336	grep "To: isp@example.com" stdout
1337'
1338
1339test_expect_success $PREREQ 'sendemail.identity: --no-identity clears previous identity' '
1340	git -c sendemail.identity=cloud send-email \
1341		--no-identity \
1342		--dry-run \
1343		--from="nobody@example.com" \
1344		$patches >stdout &&
1345	grep "To: default@example.com" stdout
1346'
1347
1348test_expect_success $PREREQ 'sendemail.identity: bool identity variable existence overrides' '
1349	git -c sendemail.identity=cloud \
1350		-c sendemail.xmailer=true \
1351		-c sendemail.cloud.xmailer=false \
1352		send-email \
1353		--dry-run \
1354		--from="nobody@example.com" \
1355		$patches >stdout &&
1356	grep "To: cloud@example.com" stdout &&
1357	! grep "X-Mailer" stdout
1358'
1359
1360test_expect_success $PREREQ 'sendemail.identity: bool variable fallback' '
1361	git -c sendemail.identity=cloud \
1362		-c sendemail.xmailer=false \
1363		send-email \
1364		--dry-run \
1365		--from="nobody@example.com" \
1366		$patches >stdout &&
1367	grep "To: cloud@example.com" stdout &&
1368	! grep "X-Mailer" stdout
1369'
1370
1371test_expect_success $PREREQ 'sendemail.identity: bool variable without a value' '
1372	git -c sendemail.xmailer \
1373		send-email \
1374		--dry-run \
1375		--from="nobody@example.com" \
1376		$patches >stdout &&
1377	grep "To: default@example.com" stdout &&
1378	grep "X-Mailer" stdout
1379'
1380
1381test_expect_success $PREREQ '--no-to overrides sendemail.to' '
1382	git send-email \
1383		--dry-run \
1384		--from="Example <nobody@example.com>" \
1385		--no-to \
1386		--to=nobody@example.com \
1387		$patches >stdout &&
1388	grep "To: nobody@example.com" stdout &&
1389	! grep "To: Somebody <somebody@ex.com>" stdout
1390'
1391
1392test_expect_success $PREREQ 'sendemail.cc works' '
1393	git config --replace-all sendemail.cc "Somebody <somebody@ex.com>" &&
1394	git send-email \
1395		--dry-run \
1396		--from="Example <nobody@example.com>" \
1397		--to=nobody@example.com \
1398		$patches >stdout &&
1399	grep "Cc: Somebody <somebody@ex.com>" stdout
1400'
1401
1402test_expect_success $PREREQ '--no-cc overrides sendemail.cc' '
1403	git send-email \
1404		--dry-run \
1405		--from="Example <nobody@example.com>" \
1406		--no-cc \
1407		--cc=bodies@example.com \
1408		--to=nobody@example.com \
1409		$patches >stdout &&
1410	grep "Cc: bodies@example.com" stdout &&
1411	! grep "Cc: Somebody <somebody@ex.com>" stdout
1412'
1413
1414test_expect_success $PREREQ 'sendemail.bcc works' '
1415	git config --replace-all sendemail.bcc "Other <other@ex.com>" &&
1416	git send-email \
1417		--dry-run \
1418		--from="Example <nobody@example.com>" \
1419		--to=nobody@example.com \
1420		--smtp-server relay.example.com \
1421		$patches >stdout &&
1422	grep "RCPT TO:<other@ex.com>" stdout
1423'
1424
1425test_expect_success $PREREQ '--no-bcc overrides sendemail.bcc' '
1426	git send-email \
1427		--dry-run \
1428		--from="Example <nobody@example.com>" \
1429		--no-bcc \
1430		--bcc=bodies@example.com \
1431		--to=nobody@example.com \
1432		--smtp-server relay.example.com \
1433		$patches >stdout &&
1434	grep "RCPT TO:<bodies@example.com>" stdout &&
1435	! grep "RCPT TO:<other@ex.com>" stdout
1436'
1437
1438test_expect_success $PREREQ 'patches To headers are used by default' '
1439	patch=$(git format-patch -1 --to="bodies@example.com") &&
1440	test_when_finished "rm $patch" &&
1441	git send-email \
1442		--dry-run \
1443		--from="Example <nobody@example.com>" \
1444		--smtp-server relay.example.com \
1445		$patch >stdout &&
1446	grep "RCPT TO:<bodies@example.com>" stdout
1447'
1448
1449test_expect_success $PREREQ 'patches To headers are appended to' '
1450	patch=$(git format-patch -1 --to="bodies@example.com") &&
1451	test_when_finished "rm $patch" &&
1452	git send-email \
1453		--dry-run \
1454		--from="Example <nobody@example.com>" \
1455		--to=nobody@example.com \
1456		--smtp-server relay.example.com \
1457		$patch >stdout &&
1458	grep "RCPT TO:<bodies@example.com>" stdout &&
1459	grep "RCPT TO:<nobody@example.com>" stdout
1460'
1461
1462test_expect_success $PREREQ 'To headers from files reset each patch' '
1463	patch1=$(git format-patch -1 --to="bodies@example.com") &&
1464	patch2=$(git format-patch -1 --to="other@example.com" HEAD~) &&
1465	test_when_finished "rm $patch1 && rm $patch2" &&
1466	git send-email \
1467		--dry-run \
1468		--from="Example <nobody@example.com>" \
1469		--to="nobody@example.com" \
1470		--smtp-server relay.example.com \
1471		$patch1 $patch2 >stdout &&
1472	test $(grep -c "RCPT TO:<bodies@example.com>" stdout) = 1 &&
1473	test $(grep -c "RCPT TO:<nobody@example.com>" stdout) = 2 &&
1474	test $(grep -c "RCPT TO:<other@example.com>" stdout) = 1
1475'
1476
1477test_expect_success $PREREQ 'setup expect' '
1478cat >email-using-8bit <<\EOF
1479From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
1480Message-Id: <bogus-message-id@example.com>
1481From: author@example.com
1482Date: Sat, 12 Jun 2010 15:53:58 +0200
1483Subject: subject goes here
1484
1485Dieser deutsche Text enthält einen Umlaut!
1486EOF
1487'
1488
1489test_expect_success $PREREQ 'setup expect' '
1490	echo "Subject: subject goes here" >expected
1491'
1492
1493test_expect_success $PREREQ 'ASCII subject is not RFC2047 quoted' '
1494	clean_fake_sendmail &&
1495	echo bogus |
1496	git send-email --from=author@example.com --to=nobody@example.com \
1497			--smtp-server="$(pwd)/fake.sendmail" \
1498			--8bit-encoding=UTF-8 \
1499			email-using-8bit >stdout &&
1500	grep "Subject" msgtxt1 >actual &&
1501	test_cmp expected actual
1502'
1503
1504test_expect_success $PREREQ 'setup expect' '
1505	cat >content-type-decl <<-\EOF
1506	MIME-Version: 1.0
1507	Content-Type: text/plain; charset=UTF-8
1508	Content-Transfer-Encoding: 8bit
1509	EOF
1510'
1511
1512test_expect_success $PREREQ 'asks about and fixes 8bit encodings' '
1513	clean_fake_sendmail &&
1514	echo |
1515	git send-email --from=author@example.com --to=nobody@example.com \
1516			--smtp-server="$(pwd)/fake.sendmail" \
1517			email-using-8bit >stdout &&
1518	grep "do not declare a Content-Transfer-Encoding" stdout &&
1519	grep email-using-8bit stdout &&
1520	grep "Which 8bit encoding" stdout &&
1521	egrep "Content|MIME" msgtxt1 >actual &&
1522	test_cmp content-type-decl actual
1523'
1524
1525test_expect_success $PREREQ 'sendemail.8bitEncoding works' '
1526	clean_fake_sendmail &&
1527	git config sendemail.assume8bitEncoding UTF-8 &&
1528	echo bogus |
1529	git send-email --from=author@example.com --to=nobody@example.com \
1530			--smtp-server="$(pwd)/fake.sendmail" \
1531			email-using-8bit >stdout &&
1532	egrep "Content|MIME" msgtxt1 >actual &&
1533	test_cmp content-type-decl actual
1534'
1535
1536test_expect_success $PREREQ 'sendemail.8bitEncoding in .git/config overrides --global .gitconfig' '
1537	clean_fake_sendmail &&
1538	git config sendemail.assume8bitEncoding UTF-8 &&
1539	test_when_finished "rm -rf home" &&
1540	mkdir home &&
1541	git config -f home/.gitconfig sendemail.assume8bitEncoding "bogus too" &&
1542	echo bogus |
1543	env HOME="$(pwd)/home" DEBUG=1 \
1544	git send-email --from=author@example.com --to=nobody@example.com \
1545			--smtp-server="$(pwd)/fake.sendmail" \
1546			email-using-8bit >stdout &&
1547	egrep "Content|MIME" msgtxt1 >actual &&
1548	test_cmp content-type-decl actual
1549'
1550
1551test_expect_success $PREREQ '--8bit-encoding overrides sendemail.8bitEncoding' '
1552	clean_fake_sendmail &&
1553	git config sendemail.assume8bitEncoding "bogus too" &&
1554	echo bogus |
1555	git send-email --from=author@example.com --to=nobody@example.com \
1556			--smtp-server="$(pwd)/fake.sendmail" \
1557			--8bit-encoding=UTF-8 \
1558			email-using-8bit >stdout &&
1559	egrep "Content|MIME" msgtxt1 >actual &&
1560	test_cmp content-type-decl actual
1561'
1562
1563test_expect_success $PREREQ 'setup expect' '
1564	cat >email-using-8bit <<-\EOF
1565	From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
1566	Message-Id: <bogus-message-id@example.com>
1567	From: author@example.com
1568	Date: Sat, 12 Jun 2010 15:53:58 +0200
1569	Subject: Dieser Betreff enthält auch einen Umlaut!
1570
1571	Nothing to see here.
1572	EOF
1573'
1574
1575test_expect_success $PREREQ 'setup expect' '
1576	cat >expected <<-\EOF
1577	Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?=
1578	EOF
1579'
1580
1581test_expect_success $PREREQ '--8bit-encoding also treats subject' '
1582	clean_fake_sendmail &&
1583	echo bogus |
1584	git send-email --from=author@example.com --to=nobody@example.com \
1585			--smtp-server="$(pwd)/fake.sendmail" \
1586			--8bit-encoding=UTF-8 \
1587			email-using-8bit >stdout &&
1588	grep "Subject" msgtxt1 >actual &&
1589	test_cmp expected actual
1590'
1591
1592test_expect_success $PREREQ 'setup expect' '
1593	cat >email-using-8bit <<-\EOF
1594	From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
1595	Message-Id: <bogus-message-id@example.com>
1596	From: A U Thor <author@example.com>
1597	Date: Sat, 12 Jun 2010 15:53:58 +0200
1598	Content-Type: text/plain; charset=UTF-8
1599	Subject: Nothing to see here.
1600
1601	Dieser Betreff enthält auch einen Umlaut!
1602	EOF
1603'
1604
1605test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEncoding' '
1606	clean_fake_sendmail &&
1607	test_must_fail git -c sendemail.transferEncoding=8bit \
1608		send-email \
1609		--transfer-encoding=7bit \
1610		--smtp-server="$(pwd)/fake.sendmail" \
1611		email-using-8bit \
1612		2>errors >out &&
1613	grep "cannot send message as 7bit" errors &&
1614	test -z "$(ls msgtxt*)"
1615'
1616
1617test_expect_success $PREREQ 'sendemail.transferEncoding via config' '
1618	clean_fake_sendmail &&
1619	test_must_fail git -c sendemail.transferEncoding=7bit \
1620		send-email \
1621		--smtp-server="$(pwd)/fake.sendmail" \
1622		email-using-8bit \
1623		2>errors >out &&
1624	grep "cannot send message as 7bit" errors &&
1625	test -z "$(ls msgtxt*)"
1626'
1627
1628test_expect_success $PREREQ 'sendemail.transferEncoding via cli' '
1629	clean_fake_sendmail &&
1630	test_must_fail git send-email \
1631		--transfer-encoding=7bit \
1632		--smtp-server="$(pwd)/fake.sendmail" \
1633		email-using-8bit \
1634		2>errors >out &&
1635	grep "cannot send message as 7bit" errors &&
1636	test -z "$(ls msgtxt*)"
1637'
1638
1639test_expect_success $PREREQ 'setup expect' '
1640	cat >expected <<-\EOF
1641	Dieser Betreff enth=C3=A4lt auch einen Umlaut!
1642	EOF
1643'
1644
1645test_expect_success $PREREQ '8-bit and sendemail.transferencoding=quoted-printable' '
1646	clean_fake_sendmail &&
1647	git send-email \
1648		--transfer-encoding=quoted-printable \
1649		--smtp-server="$(pwd)/fake.sendmail" \
1650		email-using-8bit \
1651		2>errors >out &&
1652	sed "1,/^$/d" msgtxt1 >actual &&
1653	test_cmp expected actual
1654'
1655
1656test_expect_success $PREREQ 'setup expect' '
1657	cat >expected <<-\EOF
1658	RGllc2VyIEJldHJlZmYgZW50aMOkbHQgYXVjaCBlaW5lbiBVbWxhdXQhCg==
1659	EOF
1660'
1661
1662test_expect_success $PREREQ '8-bit and sendemail.transferencoding=base64' '
1663	clean_fake_sendmail &&
1664	git send-email \
1665		--transfer-encoding=base64 \
1666		--smtp-server="$(pwd)/fake.sendmail" \
1667		email-using-8bit \
1668		2>errors >out &&
1669	sed "1,/^$/d" msgtxt1 >actual &&
1670	test_cmp expected actual
1671'
1672
1673test_expect_success $PREREQ 'setup expect' '
1674	cat >email-using-qp <<-\EOF
1675	From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
1676	Message-Id: <bogus-message-id@example.com>
1677	From: A U Thor <author@example.com>
1678	Date: Sat, 12 Jun 2010 15:53:58 +0200
1679	MIME-Version: 1.0
1680	Content-Transfer-Encoding: quoted-printable
1681	Content-Type: text/plain; charset=UTF-8
1682	Subject: Nothing to see here.
1683
1684	Dieser Betreff enth=C3=A4lt auch einen Umlaut!
1685	EOF
1686'
1687
1688test_expect_success $PREREQ 'convert from quoted-printable to base64' '
1689	clean_fake_sendmail &&
1690	git send-email \
1691		--transfer-encoding=base64 \
1692		--smtp-server="$(pwd)/fake.sendmail" \
1693		email-using-qp \
1694		2>errors >out &&
1695	sed "1,/^$/d" msgtxt1 >actual &&
1696	test_cmp expected actual
1697'
1698
1699test_expect_success $PREREQ 'setup expect' "
1700tr -d '\\015' | tr '%' '\\015' >email-using-crlf <<EOF
1701From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
1702Message-Id: <bogus-message-id@example.com>
1703From: A U Thor <author@example.com>
1704Date: Sat, 12 Jun 2010 15:53:58 +0200
1705Content-Type: text/plain; charset=UTF-8
1706Subject: Nothing to see here.
1707
1708Look, I have a CRLF and an = sign!%
1709EOF
1710"
1711
1712test_expect_success $PREREQ 'setup expect' '
1713	cat >expected <<-\EOF
1714	Look, I have a CRLF and an =3D sign!=0D
1715	EOF
1716'
1717
1718test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=quoted-printable' '
1719	clean_fake_sendmail &&
1720	git send-email \
1721		--transfer-encoding=quoted-printable \
1722		--smtp-server="$(pwd)/fake.sendmail" \
1723		email-using-crlf \
1724		2>errors >out &&
1725	sed "1,/^$/d" msgtxt1 >actual &&
1726	test_cmp expected actual
1727'
1728
1729test_expect_success $PREREQ 'setup expect' '
1730	cat >expected <<-\EOF
1731	TG9vaywgSSBoYXZlIGEgQ1JMRiBhbmQgYW4gPSBzaWduIQ0K
1732	EOF
1733'
1734
1735test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=base64' '
1736	clean_fake_sendmail &&
1737	git send-email \
1738		--transfer-encoding=base64 \
1739		--smtp-server="$(pwd)/fake.sendmail" \
1740		email-using-crlf \
1741		2>errors >out &&
1742	sed "1,/^$/d" msgtxt1 >actual &&
1743	test_cmp expected actual
1744'
1745
1746
1747# Note that the patches in this test are deliberately out of order; we
1748# want to make sure it works even if the cover-letter is not in the
1749# first mail.
1750test_expect_success $PREREQ 'refusing to send cover letter template' '
1751	clean_fake_sendmail &&
1752	rm -fr outdir &&
1753	git format-patch --cover-letter -2 -o outdir &&
1754	test_must_fail git send-email \
1755		--from="Example <nobody@example.com>" \
1756		--to=nobody@example.com \
1757		--smtp-server="$(pwd)/fake.sendmail" \
1758		outdir/0002-*.patch \
1759		outdir/0000-*.patch \
1760		outdir/0001-*.patch \
1761		2>errors >out &&
1762	grep "SUBJECT HERE" errors &&
1763	test -z "$(ls msgtxt*)"
1764'
1765
1766test_expect_success $PREREQ '--force sends cover letter template anyway' '
1767	clean_fake_sendmail &&
1768	rm -fr outdir &&
1769	git format-patch --cover-letter -2 -o outdir &&
1770	git send-email \
1771		--force \
1772		--from="Example <nobody@example.com>" \
1773		--to=nobody@example.com \
1774		--smtp-server="$(pwd)/fake.sendmail" \
1775		outdir/0002-*.patch \
1776		outdir/0000-*.patch \
1777		outdir/0001-*.patch \
1778		2>errors >out &&
1779	! grep "SUBJECT HERE" errors &&
1780	test -n "$(ls msgtxt*)"
1781'
1782
1783test_cover_addresses () {
1784	header="$1"
1785	shift
1786	clean_fake_sendmail &&
1787	rm -fr outdir &&
1788	git format-patch --cover-letter -2 -o outdir &&
1789	cover=$(echo outdir/0000-*.patch) &&
1790	mv $cover cover-to-edit.patch &&
1791	perl -pe "s/^From:/$header: extra\@address.com\nFrom:/" cover-to-edit.patch >"$cover" &&
1792	git send-email \
1793		--force \
1794		--from="Example <nobody@example.com>" \
1795		--no-to --no-cc \
1796		"$@" \
1797		--smtp-server="$(pwd)/fake.sendmail" \
1798		outdir/0000-*.patch \
1799		outdir/0001-*.patch \
1800		outdir/0002-*.patch \
1801		2>errors >out &&
1802	grep "^$header: extra@address.com" msgtxt1 >to1 &&
1803	grep "^$header: extra@address.com" msgtxt2 >to2 &&
1804	grep "^$header: extra@address.com" msgtxt3 >to3 &&
1805	test_line_count = 1 to1 &&
1806	test_line_count = 1 to2 &&
1807	test_line_count = 1 to3
1808}
1809
1810test_expect_success $PREREQ 'to-cover adds To to all mail' '
1811	test_cover_addresses "To" --to-cover
1812'
1813
1814test_expect_success $PREREQ 'cc-cover adds Cc to all mail' '
1815	test_cover_addresses "Cc" --cc-cover
1816'
1817
1818test_expect_success $PREREQ 'tocover adds To to all mail' '
1819	test_config sendemail.tocover true &&
1820	test_cover_addresses "To"
1821'
1822
1823test_expect_success $PREREQ 'cccover adds Cc to all mail' '
1824	test_config sendemail.cccover true &&
1825	test_cover_addresses "Cc"
1826'
1827
1828test_expect_success $PREREQ 'escaped quotes in sendemail.aliasfiletype=mutt' '
1829	clean_fake_sendmail &&
1830	echo "alias sbd \\\"Dot U. Sir\\\" <somebody@example.org>" >.mutt &&
1831	git config --replace-all sendemail.aliasesfile "$(pwd)/.mutt" &&
1832	git config sendemail.aliasfiletype mutt &&
1833	git send-email \
1834		--from="Example <nobody@example.com>" \
1835		--to=sbd \
1836		--smtp-server="$(pwd)/fake.sendmail" \
1837		outdir/0001-*.patch \
1838		2>errors >out &&
1839	grep "^!somebody@example\.org!$" commandline1 &&
1840	grep -F "To: \"Dot U. Sir\" <somebody@example.org>" out
1841'
1842
1843test_expect_success $PREREQ 'sendemail.aliasfiletype=mailrc' '
1844	clean_fake_sendmail &&
1845	echo "alias sbd  somebody@example.org" >.mailrc &&
1846	git config --replace-all sendemail.aliasesfile "$(pwd)/.mailrc" &&
1847	git config sendemail.aliasfiletype mailrc &&
1848	git send-email \
1849		--from="Example <nobody@example.com>" \
1850		--to=sbd \
1851		--smtp-server="$(pwd)/fake.sendmail" \
1852		outdir/0001-*.patch \
1853		2>errors >out &&
1854	grep "^!somebody@example\.org!$" commandline1
1855'
1856
1857test_expect_success $PREREQ 'sendemail.aliasesfile=~/.mailrc' '
1858	clean_fake_sendmail &&
1859	echo "alias sbd  someone@example.org" >"$HOME/.mailrc" &&
1860	git config --replace-all sendemail.aliasesfile "~/.mailrc" &&
1861	git config sendemail.aliasfiletype mailrc &&
1862	git send-email \
1863		--from="Example <nobody@example.com>" \
1864		--to=sbd \
1865		--smtp-server="$(pwd)/fake.sendmail" \
1866		outdir/0001-*.patch \
1867		2>errors >out &&
1868	grep "^!someone@example\.org!$" commandline1
1869'
1870
1871test_dump_aliases () {
1872	msg="$1" && shift &&
1873	filetype="$1" && shift &&
1874	printf '%s\n' "$@" >expect &&
1875	cat >.tmp-email-aliases &&
1876
1877	test_expect_success $PREREQ "$msg" '
1878		clean_fake_sendmail && rm -fr outdir &&
1879		git config --replace-all sendemail.aliasesfile \
1880			"$(pwd)/.tmp-email-aliases" &&
1881		git config sendemail.aliasfiletype "$filetype" &&
1882		git send-email --dump-aliases 2>errors >actual &&
1883		test_cmp expect actual
1884	'
1885}
1886
1887test_dump_aliases '--dump-aliases sendmail format' \
1888	'sendmail' \
1889	'abgroup' \
1890	'alice' \
1891	'bcgrp' \
1892	'bob' \
1893	'chloe' <<-\EOF
1894	alice: Alice W Land <awol@example.com>
1895	bob: Robert Bobbyton <bob@example.com>
1896	chloe: chloe@example.com
1897	abgroup: alice, bob
1898	bcgrp: bob, chloe, Other <o@example.com>
1899	EOF
1900
1901test_dump_aliases '--dump-aliases mutt format' \
1902	'mutt' \
1903	'alice' \
1904	'bob' \
1905	'chloe' \
1906	'donald' <<-\EOF
1907	alias alice Alice W Land <awol@example.com>
1908	alias donald Donald C Carlton <donc@example.com>
1909	alias bob Robert Bobbyton <bob@example.com>
1910	alias chloe chloe@example.com
1911	EOF
1912
1913test_dump_aliases '--dump-aliases mailrc format' \
1914	'mailrc' \
1915	'alice' \
1916	'bob' \
1917	'chloe' \
1918	'eve' <<-\EOF
1919	alias alice   Alice W Land <awol@example.com>
1920	alias eve     Eve <eve@example.com>
1921	alias bob     Robert Bobbyton <bob@example.com>
1922	alias chloe   chloe@example.com
1923	EOF
1924
1925test_dump_aliases '--dump-aliases pine format' \
1926	'pine' \
1927	'alice' \
1928	'bob' \
1929	'chloe' \
1930	'eve' <<-\EOF
1931	alice	Alice W Land	<awol@example.com>
1932	eve	Eve	<eve@example.com>
1933	bob	Robert	Bobbyton <bob@example.com>
1934	chloe		chloe@example.com
1935	EOF
1936
1937test_dump_aliases '--dump-aliases gnus format' \
1938	'gnus' \
1939	'alice' \
1940	'bob' \
1941	'chloe' \
1942	'eve' <<-\EOF
1943	(define-mail-alias "alice" "awol@example.com")
1944	(define-mail-alias "eve" "eve@example.com")
1945	(define-mail-alias "bob" "bob@example.com")
1946	(define-mail-alias "chloe" "chloe@example.com")
1947	EOF
1948
1949test_expect_success '--dump-aliases must be used alone' '
1950	test_must_fail git send-email --dump-aliases --to=janice@example.com -1 refs/heads/accounting
1951'
1952
1953test_expect_success $PREREQ 'aliases and sendemail.identity' '
1954	test_must_fail git \
1955		-c sendemail.identity=cloud \
1956		-c sendemail.aliasesfile=default-aliases \
1957		-c sendemail.cloud.aliasesfile=cloud-aliases \
1958		send-email -1 2>stderr &&
1959	test_i18ngrep "cloud-aliases" stderr
1960'
1961
1962test_sendmail_aliases () {
1963	msg="$1" && shift &&
1964	expect="$@" &&
1965	cat >.tmp-email-aliases &&
1966
1967	test_expect_success $PREREQ "$msg" '
1968		clean_fake_sendmail && rm -fr outdir &&
1969		git format-patch -1 -o outdir &&
1970		git config --replace-all sendemail.aliasesfile \
1971			"$(pwd)/.tmp-email-aliases" &&
1972		git config sendemail.aliasfiletype sendmail &&
1973		git send-email \
1974			--from="Example <nobody@example.com>" \
1975			--to=alice --to=bcgrp \
1976			--smtp-server="$(pwd)/fake.sendmail" \
1977			outdir/0001-*.patch \
1978			2>errors >out &&
1979		for i in $expect
1980		do
1981			grep "^!$i!$" commandline1 || return 1
1982		done
1983	'
1984}
1985
1986test_sendmail_aliases 'sendemail.aliasfiletype=sendmail' \
1987	'awol@example\.com' \
1988	'bob@example\.com' \
1989	'chloe@example\.com' \
1990	'o@example\.com' <<-\EOF
1991	alice: Alice W Land <awol@example.com>
1992	bob: Robert Bobbyton <bob@example.com>
1993	# this is a comment
1994	   # this is also a comment
1995	chloe: chloe@example.com
1996	abgroup: alice, bob
1997	bcgrp: bob, chloe, Other <o@example.com>
1998	EOF
1999
2000test_sendmail_aliases 'sendmail aliases line folding' \
2001	alice1 \
2002	bob1 bob2 \
2003	chuck1 chuck2 \
2004	darla1 darla2 darla3 \
2005	elton1 elton2 elton3 \
2006	fred1 fred2 \
2007	greg1 <<-\EOF
2008	alice: alice1
2009	bob: bob1,\
2010	bob2
2011	chuck: chuck1,
2012	    chuck2
2013	darla: darla1,\
2014	darla2,
2015	    darla3
2016	elton: elton1,
2017	    elton2,\
2018	elton3
2019	fred: fred1,\
2020	    fred2
2021	greg: greg1
2022	bcgrp: bob, chuck, darla, elton, fred, greg
2023	EOF
2024
2025test_sendmail_aliases 'sendmail aliases tolerate bogus line folding' \
2026	alice1 bob1 <<-\EOF
2027	    alice: alice1
2028	bcgrp: bob1\
2029	EOF
2030
2031test_sendmail_aliases 'sendmail aliases empty' alice bcgrp <<-\EOF
2032	EOF
2033
2034test_expect_success $PREREQ 'alias support in To header' '
2035	clean_fake_sendmail &&
2036	echo "alias sbd  someone@example.org" >.mailrc &&
2037	test_config sendemail.aliasesfile ".mailrc" &&
2038	test_config sendemail.aliasfiletype mailrc &&
2039	git format-patch --stdout -1 --to=sbd >aliased.patch &&
2040	git send-email \
2041		--from="Example <nobody@example.com>" \
2042		--smtp-server="$(pwd)/fake.sendmail" \
2043		aliased.patch \
2044		2>errors >out &&
2045	grep "^!someone@example\.org!$" commandline1
2046'
2047
2048test_expect_success $PREREQ 'alias support in Cc header' '
2049	clean_fake_sendmail &&
2050	echo "alias sbd  someone@example.org" >.mailrc &&
2051	test_config sendemail.aliasesfile ".mailrc" &&
2052	test_config sendemail.aliasfiletype mailrc &&
2053	git format-patch --stdout -1 --cc=sbd >aliased.patch &&
2054	git send-email \
2055		--from="Example <nobody@example.com>" \
2056		--smtp-server="$(pwd)/fake.sendmail" \
2057		aliased.patch \
2058		2>errors >out &&
2059	grep "^!someone@example\.org!$" commandline1
2060'
2061
2062test_expect_success $PREREQ 'tocmd works with aliases' '
2063	clean_fake_sendmail &&
2064	echo "alias sbd  someone@example.org" >.mailrc &&
2065	test_config sendemail.aliasesfile ".mailrc" &&
2066	test_config sendemail.aliasfiletype mailrc &&
2067	git format-patch --stdout -1 >tocmd.patch &&
2068	echo tocmd--sbd >>tocmd.patch &&
2069	git send-email \
2070		--from="Example <nobody@example.com>" \
2071		--to-cmd=./tocmd-sed \
2072		--smtp-server="$(pwd)/fake.sendmail" \
2073		tocmd.patch \
2074		2>errors >out &&
2075	grep "^!someone@example\.org!$" commandline1
2076'
2077
2078test_expect_success $PREREQ 'cccmd works with aliases' '
2079	clean_fake_sendmail &&
2080	echo "alias sbd  someone@example.org" >.mailrc &&
2081	test_config sendemail.aliasesfile ".mailrc" &&
2082	test_config sendemail.aliasfiletype mailrc &&
2083	git format-patch --stdout -1 >cccmd.patch &&
2084	echo cccmd--sbd >>cccmd.patch &&
2085	git send-email \
2086		--from="Example <nobody@example.com>" \
2087		--cc-cmd=./cccmd-sed \
2088		--smtp-server="$(pwd)/fake.sendmail" \
2089		cccmd.patch \
2090		2>errors >out &&
2091	grep "^!someone@example\.org!$" commandline1
2092'
2093
2094do_xmailer_test () {
2095	expected=$1 params=$2 &&
2096	git format-patch -1 &&
2097	git send-email \
2098		--from="Example <nobody@example.com>" \
2099		--to=someone@example.com \
2100		--smtp-server="$(pwd)/fake.sendmail" \
2101		$params \
2102		0001-*.patch \
2103		2>errors >out &&
2104	{ grep '^X-Mailer:' out || :; } >mailer &&
2105	test_line_count = $expected mailer
2106}
2107
2108test_expect_success $PREREQ '--[no-]xmailer without any configuration' '
2109	do_xmailer_test 1 "--xmailer" &&
2110	do_xmailer_test 0 "--no-xmailer"
2111'
2112
2113test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=true' '
2114	test_config sendemail.xmailer true &&
2115	do_xmailer_test 1 "" &&
2116	do_xmailer_test 0 "--no-xmailer" &&
2117	do_xmailer_test 1 "--xmailer"
2118'
2119
2120test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer' '
2121	test_when_finished "test_unconfig sendemail.xmailer" &&
2122	cat >>.git/config <<-\EOF &&
2123	[sendemail]
2124		xmailer
2125	EOF
2126	test_config sendemail.xmailer true &&
2127	do_xmailer_test 1 "" &&
2128	do_xmailer_test 0 "--no-xmailer" &&
2129	do_xmailer_test 1 "--xmailer"
2130'
2131
2132test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=false' '
2133	test_config sendemail.xmailer false &&
2134	do_xmailer_test 0 "" &&
2135	do_xmailer_test 0 "--no-xmailer" &&
2136	do_xmailer_test 1 "--xmailer"
2137'
2138
2139test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=' '
2140	test_config sendemail.xmailer "" &&
2141	do_xmailer_test 0 "" &&
2142	do_xmailer_test 0 "--no-xmailer" &&
2143	do_xmailer_test 1 "--xmailer"
2144'
2145
2146test_expect_success $PREREQ 'setup expected-list' '
2147	git send-email \
2148	--dry-run \
2149	--from="Example <from@example.com>" \
2150	--to="To 1 <to1@example.com>" \
2151	--to="to2@example.com" \
2152	--to="to3@example.com" \
2153	--cc="Cc 1 <cc1@example.com>" \
2154	--cc="Cc2 <cc2@example.com>" \
2155	--bcc="bcc1@example.com" \
2156	--bcc="bcc2@example.com" \
2157	0001-add-main.patch | replace_variable_fields \
2158	>expected-list
2159'
2160
2161test_expect_success $PREREQ 'use email list in --cc --to and --bcc' '
2162	git send-email \
2163	--dry-run \
2164	--from="Example <from@example.com>" \
2165	--to="To 1 <to1@example.com>, to2@example.com" \
2166	--to="to3@example.com" \
2167	--cc="Cc 1 <cc1@example.com>, Cc2 <cc2@example.com>" \
2168	--bcc="bcc1@example.com, bcc2@example.com" \
2169	0001-add-main.patch | replace_variable_fields \
2170	>actual-list &&
2171	test_cmp expected-list actual-list
2172'
2173
2174test_expect_success $PREREQ 'aliases work with email list' '
2175	echo "alias to2 to2@example.com" >.mutt &&
2176	echo "alias cc1 Cc 1 <cc1@example.com>" >>.mutt &&
2177	test_config sendemail.aliasesfile ".mutt" &&
2178	test_config sendemail.aliasfiletype mutt &&
2179	git send-email \
2180	--dry-run \
2181	--from="Example <from@example.com>" \
2182	--to="To 1 <to1@example.com>, to2, to3@example.com" \
2183	--cc="cc1, Cc2 <cc2@example.com>" \
2184	--bcc="bcc1@example.com, bcc2@example.com" \
2185	0001-add-main.patch | replace_variable_fields \
2186	>actual-list &&
2187	test_cmp expected-list actual-list
2188'
2189
2190test_expect_success $PREREQ 'leading and trailing whitespaces are removed' '
2191	echo "alias to2 to2@example.com" >.mutt &&
2192	echo "alias cc1 Cc 1 <cc1@example.com>" >>.mutt &&
2193	test_config sendemail.aliasesfile ".mutt" &&
2194	test_config sendemail.aliasfiletype mutt &&
2195	TO1=$(echo "QTo 1 <to1@example.com>" | q_to_tab) &&
2196	TO2=$(echo "QZto2" | qz_to_tab_space) &&
2197	CC1=$(echo "cc1" | append_cr) &&
2198	BCC1=$(echo " bcc1@example.com Q" | q_to_nul) &&
2199	git send-email \
2200	--dry-run \
2201	--from="	Example <from@example.com>" \
2202	--to="$TO1" \
2203	--to="$TO2" \
2204	--to="  to3@example.com   " \
2205	--cc="$CC1" \
2206	--cc="Cc2 <cc2@example.com>" \
2207	--bcc="$BCC1" \
2208	--bcc="bcc2@example.com" \
2209	0001-add-main.patch | replace_variable_fields \
2210	>actual-list &&
2211	test_cmp expected-list actual-list
2212'
2213
2214test_expect_success $PREREQ 'test using command name with --sendmail-cmd' '
2215	clean_fake_sendmail &&
2216	PATH="$PWD:$PATH" \
2217	git send-email \
2218		--from="Example <nobody@example.com>" \
2219		--to=nobody@example.com \
2220		--sendmail-cmd="fake.sendmail" \
2221		HEAD^ &&
2222	test_path_is_file commandline1
2223'
2224
2225test_expect_success $PREREQ 'test using arguments with --sendmail-cmd' '
2226	clean_fake_sendmail &&
2227	git send-email \
2228		--from="Example <nobody@example.com>" \
2229		--to=nobody@example.com \
2230		--sendmail-cmd='\''"$(pwd)/fake.sendmail" -f nobody@example.com'\'' \
2231		HEAD^ &&
2232	test_path_is_file commandline1
2233'
2234
2235test_expect_success $PREREQ 'test shell expression with --sendmail-cmd' '
2236	clean_fake_sendmail &&
2237	git send-email \
2238		--from="Example <nobody@example.com>" \
2239		--to=nobody@example.com \
2240		--sendmail-cmd='\''f() { "$(pwd)/fake.sendmail" "$@"; };f'\'' \
2241		HEAD^ &&
2242	test_path_is_file commandline1
2243'
2244
2245test_expect_success $PREREQ 'set up in-reply-to/references patches' '
2246	cat >has-reply.patch <<-\EOF &&
2247	From: A U Thor <author@example.com>
2248	Subject: patch with in-reply-to
2249	Message-ID: <patch.with.in.reply.to@example.com>
2250	In-Reply-To: <replied.to@example.com>
2251	References: <replied.to@example.com>
2252
2253	This is the body.
2254	EOF
2255	cat >no-reply.patch <<-\EOF
2256	From: A U Thor <author@example.com>
2257	Subject: patch without in-reply-to
2258	Message-ID: <patch.without.in.reply.to@example.com>
2259
2260	This is the body.
2261	EOF
2262'
2263
2264test_expect_success $PREREQ 'patch reply headers correct with --no-thread' '
2265	clean_fake_sendmail &&
2266	git send-email \
2267		--no-thread \
2268		--to=nobody@example.com \
2269		--smtp-server="$(pwd)/fake.sendmail" \
2270		has-reply.patch no-reply.patch &&
2271	grep "In-Reply-To: <replied.to@example.com>" msgtxt1 &&
2272	grep "References: <replied.to@example.com>" msgtxt1 &&
2273	! grep replied.to@example.com msgtxt2
2274'
2275
2276test_expect_success $PREREQ 'cmdline in-reply-to used with --no-thread' '
2277	clean_fake_sendmail &&
2278	git send-email \
2279		--no-thread \
2280		--in-reply-to="<cmdline.reply@example.com>" \
2281		--to=nobody@example.com \
2282		--smtp-server="$(pwd)/fake.sendmail" \
2283		has-reply.patch no-reply.patch &&
2284	grep "In-Reply-To: <cmdline.reply@example.com>" msgtxt1 &&
2285	grep "References: <cmdline.reply@example.com>" msgtxt1 &&
2286	grep "In-Reply-To: <cmdline.reply@example.com>" msgtxt2 &&
2287	grep "References: <cmdline.reply@example.com>" msgtxt2
2288'
2289
2290test_expect_success $PREREQ 'invoke hook' '
2291	mkdir -p .git/hooks &&
2292
2293	write_script .git/hooks/sendemail-validate <<-\EOF &&
2294	# test that we have the correct environment variable, pwd, and
2295	# argument
2296	case "$GIT_DIR" in
2297	*.git)
2298		true
2299		;;
2300	*)
2301		false
2302		;;
2303	esac &&
2304	test -f 0001-add-main.patch &&
2305	grep "add main" "$1"
2306	EOF
2307
2308	mkdir subdir &&
2309	(
2310		# Test that it works even if we are not at the root of the
2311		# working tree
2312		cd subdir &&
2313		git send-email \
2314			--from="Example <nobody@example.com>" \
2315			--to=nobody@example.com \
2316			--smtp-server="$(pwd)/../fake.sendmail" \
2317			../0001-add-main.patch &&
2318
2319		# Verify error message when a patch is rejected by the hook
2320		sed -e "s/add main/x/" ../0001-add-main.patch >../another.patch &&
2321		test_must_fail git send-email \
2322			--from="Example <nobody@example.com>" \
2323			--to=nobody@example.com \
2324			--smtp-server="$(pwd)/../fake.sendmail" \
2325			../another.patch 2>err &&
2326		test_i18ngrep "rejected by sendemail-validate hook" err
2327	)
2328'
2329
2330test_expect_success $PREREQ 'test that send-email works outside a repo' '
2331	nongit git send-email \
2332		--from="Example <nobody@example.com>" \
2333		--to=nobody@example.com \
2334		--smtp-server="$(pwd)/fake.sendmail" \
2335		"$(pwd)/0001-add-main.patch"
2336'
2337
2338test_expect_success $PREREQ 'test that sendmail config is rejected' '
2339	test_config sendmail.program sendmail &&
2340	test_must_fail git send-email \
2341		--from="Example <nobody@example.com>" \
2342		--to=nobody@example.com \
2343		--smtp-server="$(pwd)/fake.sendmail" \
2344		HEAD^ 2>err &&
2345	test_i18ngrep "found configuration options for '"'"sendmail"'"'" err
2346'
2347
2348test_expect_success $PREREQ 'test that sendmail config rejection is specific' '
2349	test_config resendmail.program sendmail &&
2350	git send-email \
2351		--from="Example <nobody@example.com>" \
2352		--to=nobody@example.com \
2353		--smtp-server="$(pwd)/fake.sendmail" \
2354		HEAD^
2355'
2356
2357test_expect_success $PREREQ 'test forbidSendmailVariables behavior override' '
2358	test_config sendmail.program sendmail &&
2359	test_config sendemail.forbidSendmailVariables false &&
2360	git send-email \
2361		--from="Example <nobody@example.com>" \
2362		--to=nobody@example.com \
2363		--smtp-server="$(pwd)/fake.sendmail" \
2364		HEAD^
2365'
2366
2367test_done
2368