# [PATCH v2] send-email: allow use of basic email list in --cc --to and --bcc

2 messages from 2013-06-19 to 2013-06-19. Participants: jorge-juan.garcia-garcia@ensimag.imag.fr, Matthieu Moy.
Thread: https://gitlist.dev/t/34220

## jorge-juan.garcia-garcia@ensimag.imag.fr, 2013-06-19 11:34

Subject: [PATCH v2] send-email: allow use of basic email list in --cc --to and --bcc
Message-ID: <1371641640-3897-1-git-send-email-Jorge-Juan.Garcia-Garcia@ensimag.imag.fr>
URL: https://gitlist.dev/e/1371641640-3897-1-git-send-email-Jorge-Juan.Garcia-Garcia%40ensimag.imag.fr

```
From: Jorge Juan Garcia Garcia <Jorge-Juan.Garcia-Garcia@ensimag.imag.fr>

Make it so that we can use a list of email in flags
instead of having to use one flag per email address.

The use-case is to copy-paste a list of addresses from an email.
This change makes it so that we no longer need to cut the list.

The format of email list handled is pretty basic for now:
	$ git send-email --to='Foo <foo@example.com>, bar@example.com'
We thought it would be nice to have a "first-step" version which works
before handling more complex ones such as names with commas:
	$ git send-email --to='Foo, Bar <foobar@example.com>'

This artificial limitation is imposed by 79ee555b (Check and document
the options to prevent mistakes, 2006-06-21).

Signed-off-by: Mathieu Lienard--Mayor <Mathieu.Lienard--Mayor@ensimag.imag.fr>
Signed-off-by: Jorge Juan Garcia Garcia <Jorge-Juan.Garcia-Garcia@ensimag.imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
---

Changes since v1:
 - more detailed commit message, explaining the most common use-case,
   and referring to the commit which introduced the comma limitation
 - use of map in the function, to match sanitize_address_list
 - did not change the two regexp into one, because it's faster with two

 Documentation/git-send-email.txt |   21 +++++++++++++++------
 git-send-email.perl              |   36 ++++++++++++++++++++++--------------
 t/t9001-send-email.sh            |   37 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 40a9a9a..e3444cf 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -50,16 +50,22 @@ Composing
 	'sendemail.multiedit'.
 
 --bcc=<address>::
+--bcc="[<address>,...]"::
 	Specify a "Bcc:" value for each email. Default is the value of
 	'sendemail.bcc'.
-+
-The --bcc option must be repeated for each user you want on the bcc list.
+	The format supported for email list is the following:
+	"Foo <foo@example.com>, bar@example.com".
+	Please notice that the email list does not handle commas in
+	email names such as "Foo, Bar <foobar@example.com>".
 
 --cc=<address>::
+--cc="[<address>,...]"::
 	Specify a starting "Cc:" value for each email.
 	Default is the value of 'sendemail.cc'.
-+
-The --cc option must be repeated for each user you want on the cc list.
+	The format supported for email list is the following:
+	"Foo <foo@example.com>, bar@example.com".
+	Please notice that the email list does not handle commas in
+	email names such as "Foo, Bar <foobar@example.com>".
 
 --compose::
 	Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1])
@@ -111,12 +117,15 @@ is not set, this will be prompted for.
 	is not set, this will be prompted for.
 
 --to=<address>::
+--to="[<address>,...]"::
 	Specify the primary recipient of the emails generated. Generally, this
 	will be the upstream maintainer of the project involved. Default is the
 	value of the 'sendemail.to' configuration value; if that is unspecified,
 	and --to-cmd is not specified, this will be prompted for.
-+
-The --to option must be repeated for each user you want on the to list.
+	The format supported for email list is the following:
+	"Foo <foo@example.com>, bar@example.com".
+	Please notice that the email list does not handle commas in
+	email names such as "Foo, Bar <foobar@example.com>".
 
 --8bit-encoding=<encoding>::
 	When encountering a non-ASCII message or subject that does not
diff --git a/git-send-email.perl b/git-send-email.perl
index 671762b..03f3876 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -426,20 +426,6 @@ my ($repoauthor, $repocommitter);
 ($repoauthor) = Git::ident_person(@repo, 'author');
 ($repocommitter) = Git::ident_person(@repo, 'committer');
 
-# Verify the user input
-
-foreach my $entry (@initial_to) {
-	die "Comma in --to entry: $entry'\n" unless $entry !~ m/,/;
-}
-
-foreach my $entry (@initial_cc) {
-	die "Comma in --cc entry: $entry'\n" unless $entry !~ m/,/;
-}
-
-foreach my $entry (@bcclist) {
-	die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/;
-}
-
 sub parse_address_line {
 	if ($have_mail_address) {
 		return map { $_->format } Mail::Address->parse($_[0]);
@@ -1079,6 +1065,25 @@ sub smtp_auth_maybe {
 	return $auth;
 }
 
+sub split_emails {
+    my ($emails) = @_;
+    my @split_list;
+    if ($emails =~ /,/) {
+	@split_list = split(/,/, $emails);
+    } else {
+	@split_list = $emails;
+    }
+    # Removal of unwanted spaces
+    for (my $j = 0; $j <= $#split_list; $j++) {
+	$split_list[$j] =~ s/^\s+//;
+	$split_list[$j] =~ s/\s+$//;
+    }
+    return @split_list;
+}
+
+sub split_emails_list {
+	return (map { split_emails($_) } @_);
+}
 # Returns 1 if the message was sent, and 0 otherwise.
 # In actuality, the whole program dies when there
 # is an error sending a message.
@@ -1089,6 +1094,9 @@ sub send_message {
 		      not grep { $cc eq $_ || $_ =~ /<\Q${cc}\E>$/ } @recipients
 		    }
 	       @cc);
+	@cc = split_emails_list(@cc);
+	@bcclist = split_emails_list(@bcclist);
+	@recipients = split_emails_list(@recipients);
 	my $to = join (",\n\t", @recipients);
 	@recipients = unique_email_list(@recipients,@cc,@bcclist);
 	@recipients = (map { extract_valid_address_or_die($_) } @recipients);
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 9f46f22..87641bc 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -1349,4 +1349,39 @@ test_expect_success $PREREQ 'sendemail.aliasfile=~/.mailrc' '
 	grep "^!someone@example\.org!$" commandline1
 '
 
-test_done
+test_expect_success $PREREQ 'setup expected-list' '
+	git send-email \
+		--dry-run \
+		--suppress-cc=sob \
+		--from="Example <from@example.com>" \
+		--to="to1@example.com" --to="to2@example.com" \
+		--to="to3@example.com" --cc="cc0@example.com" \
+		--cc="Cc 1 <cc1@example.com>" --cc="Cc 2 <cc2@example.com>" \
+		--bcc="bcc1@example.com" --bcc="bcc2@example.com" \
+		-1 >output
+	sed	-e "s/^\(\/tmp\/\).*/\1patch/" \
+		-e "s/^\(Date:\).*/\1 DATE-STRING/" \
+		-e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
+		-e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
+		<output >expected-list
+'
+
+test_expect_success $PREREQ 'use email list in --cc --to and --bcc' '
+	git send-email \
+		--dry-run \
+		--suppress-cc=sob \
+		--from="Example <from@example.com>" \
+		--to="to1@example.com, to2@example.com,to3@example.com" \
+		--cc="cc0@example.com" \
+		--cc="Cc 1 <cc1@example.com>, Cc 2 <cc2@example.com>" \
+		--bcc="bcc1@example.com, bcc2@example.com" \
+		-1 >output
+	sed	-e "s/^\(\/tmp\/\).*/\1patch/" \
+		-e "s/^\(Date:\).*/\1 DATE-STRING/" \
+		-e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \
+		-e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" \
+		<output >actual-list &&
+	test_cmp expected-list actual-list
+'
+
+test_done
\ No newline at end of file
-- 
1.7.8

```

## Matthieu Moy, 2013-06-19 11:51

Subject: Re: [PATCH v2] send-email: allow use of basic email list in --cc --to and --bcc
Message-ID: <vpqwqpqjp3t.fsf@anie.imag.fr>
URL: https://gitlist.dev/e/vpqwqpqjp3t.fsf%40anie.imag.fr
In-Reply-To: <1371641640-3897-1-git-send-email-Jorge-Juan.Garcia-Garcia@ensimag.imag.fr>

```
Jorge-Juan.Garcia-Garcia@ensimag.imag.fr writes:

> Changes since v1:
> [...]
>  - did not change the two regexp into one, because it's faster with two

(I find it strange to describe non-change in a list of changes)

I don't think speed is an argument here: it's a one-time operation and
will be instantaneous for the user in any case.

> +sub split_emails {
> +    my ($emails) = @_;
> +    my @split_list;
> +    if ($emails =~ /,/) {
> +	@split_list = split(/,/, $emails);
> +    } else {
> +	@split_list = $emails;
> +    }

Do you need this "if"? Wouldn't split do the right thing if $emails does
not contain comma?

> +    # Removal of unwanted spaces
> +    for (my $j = 0; $j <= $#split_list; $j++) {

Sounds very un-perl-ish. Something like this maybe?

foreach $email (@emails) {
	$email =~ s/^\s+|\s+$//;
}

> +    return @split_list;
> +}

This is indented with tab/spaces mix. Please, use tabs only in Git's
source.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

```
