{"thread":{"id":"33579","subject":"[PATCH] send-email: support NNTP","startedAt":"2013-04-23T11:13:54Z","lastAt":"2013-04-25T17:35:10Z","messageCount":14,"participants":["Łukasz Stelmach","Junio C Hamano","Eric Sunshine","Thomas Rast"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"215204","messageId":"1366715634-21790-1-git-send-email-l.stelmach@samsung.com","threadId":"33579","inReplyTo":null,"subject":"[PATCH] send-email: support NNTP","fromName":"Łukasz Stelmach","fromEmail":"l.stelmach@samsung.com","sentAt":"2013-04-23T11:13:54Z","receivedAt":"2013-04-23T11:13:54Z","isPatch":true,"sender":{"key":"l.stelmach@samsung.com","avatar":"https://gravatar.com/avatar/b5f9262ad19b1b6f1e74b8eba816455e059742e8d980fdefa9321976071642fc?d=mp&s=160"},"body":"Enable sending patches to NNTP servers (Usenet, Gmane).\n---\n\nThe patch implements support for sending messages to groups on NNTP serviers.\nThe patch does not (attempts not to) change the default behavior i.e. to use sendmail\nand/or Net::SMTP. To use NNTP one needs to configure the server (see the help message)\nand protocol (\"--protocol nntp\"). Then after giving --newsgroups the\nmessage will be sent via NNTP. Like this one:\n\nperl git-send-email.perl --protocol nntp --newsgroups gmane.comp.version-control.git --nntp-server news.gmane.org 0001-send-email-support-NNTP.patch\n\n git-send-email.perl |  156 +++++++++++++++++++++++++++++++++++++++++----------\n 1 file changed, 125 insertions(+), 31 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex bd13cc8..0356635 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -54,12 +54,14 @@ git send-email [options] <file | directory | rev-list options >\n     --[no-]bcc              <str>  * Email Bcc:\n     --subject               <str>  * Email \"Subject:\"\n     --in-reply-to           <str>  * Email \"In-Reply-To:\"\n+    --newsgroups            <str>  * NNTP Newsgroups:\n     --[no-]annotate                * Review each patch that will be sent in an editor.\n     --compose                      * Open an editor for introduction.\n     --compose-encoding      <str>  * Encoding to assume for introduction.\n     --8bit-encoding         <str>  * Encoding to assume 8bit mails if undeclared\n \n   Sending:\n+    --protocol              <str>  * 'smtp' or 'nntp'. Default 'smtp'.\n     --envelope-sender       <str>  * Email envelope sender.\n     --smtp-server       <str:int>  * Outgoing SMTP server to use. The port\n                                      is optional. Default 'localhost'.\n@@ -71,6 +73,12 @@ git send-email [options] <file | directory | rev-list options >\n     --smtp-ssl                     * Deprecated. Use '--smtp-encryption ssl'.\n     --smtp-domain           <str>  * The domain name sent to HELO/EHLO handshake\n     --smtp-debug            <0|1>  * Disable, enable Net::SMTP debug.\n+    --nntp-server       <str:int>  * Outgoing NNTP server to use. The port\n+                                     is optional.\n+    --nntp-server-port      <int>  * Outgoing NNTP server port.\n+    --nntp-user             <str>  * Username for NNTP AUTHINFO.\n+    --nntp-pass             <str>  * Password for NNTP AUTHINFO.\n+    --nntp-debug            <0|1>  * Disable, enable Net::NNTP debug.\n \n   Automating:\n     --identity              <str>  * Use the sendemail.<id> options.\n@@ -138,12 +146,14 @@ sub format_2822_time {\n my $have_email_valid = eval { require Email::Valid; 1 };\n my $have_mail_address = eval { require Mail::Address; 1 };\n my $smtp;\n+my $nntp;\n my $auth;\n \n # Variables we fill in automatically, or via prompting:\n my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,\n \t$initial_reply_to,$initial_subject,@files,\n-\t$author,$sender,$smtp_authpass,$annotate,$compose,$time);\n+\t$author,$sender,$smtp_authpass,$annotate,$compose,$time,\n+\t@initial_newsgroups, @newsgroups);\n \n my $envelope_sender;\n \n@@ -192,7 +202,9 @@ sub do_edit {\n \n # Variables with corresponding config settings\n my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc);\n-my ($to_cmd, $cc_cmd);\n+my ($to_cmd, $cc_cmd, $newsgroups_cmd);\n+my ($email_protocol) = 'smtp';\n+my ($nntp_server, $nntp_server_port, $nntp_authuser, $nntp_authpass);\n my ($smtp_server, $smtp_server_port, @smtp_server_options);\n my ($smtp_authuser, $smtp_encryption);\n my ($identity, $aliasfiletype, @alias_files, $smtp_domain);\n@@ -202,6 +214,7 @@ my ($auto_8bit_encoding);\n my ($compose_encoding);\n \n my ($debug_net_smtp) = 0;\t\t# Net::SMTP, see send_message()\n+my ($debug_net_nntp) = 0;\t\t# Net::NNTP, see send_message()\n \n my $not_set_by_user = \"true but not set by the user\";\n \n@@ -235,6 +248,13 @@ my %config_settings = (\n     \"from\" => \\$sender,\n     \"assume8bitencoding\" => \\$auto_8bit_encoding,\n     \"composeencoding\" => \\$compose_encoding,\n+    \"nntpserver\" => \\$nntp_server,\n+    \"nntpserverport\" => \\$nntp_server_port,\n+    \"nntpuser\" => \\$nntp_authuser,\n+    \"nntppass\" => \\$nntp_authpass,\n+    \"protocol\" => \\$email_protocol,\n+    \"newsgroups\" => \\@initial_newsgroups,\n+    \"newsgroupscmd\" => \\$newsgroups_cmd,\n );\n \n my %config_path_settings = (\n@@ -291,6 +311,7 @@ my $rc = GetOptions(\"h\" => \\$help,\n \t\t    \"to-cmd=s\" => \\$to_cmd,\n \t\t    \"no-to\" => \\$no_to,\n \t\t    \"cc=s\" => \\@initial_cc,\n+\t\t    \"cc-cmd=s\" => \\$cc_cmd,\n \t\t    \"no-cc\" => \\$no_cc,\n \t\t    \"bcc=s\" => \\@bcclist,\n \t\t    \"no-bcc\" => \\$no_bcc,\n@@ -304,11 +325,18 @@ my $rc = GetOptions(\"h\" => \\$help,\n \t\t    \"smtp-encryption=s\" => \\$smtp_encryption,\n \t\t    \"smtp-debug:i\" => \\$debug_net_smtp,\n \t\t    \"smtp-domain:s\" => \\$smtp_domain,\n+\t\t    \"newsgroups=s\" => \\@initial_newsgroups,\n+\t\t    \"newsgroups-cmd\" => \\$newsgroups_cmd,\n+\t\t    \"nntp-server=s\" => \\$nntp_server,\n+\t\t    \"nntp-server-port=s\" => \\$nntp_server_port,\n+\t\t    \"nntp-user=s\" => \\$nntp_authuser,\n+\t\t    \"nntp-pass:s\" => \\$nntp_authpass,\n+\t\t    \"nntp-debug:i\" => \\$debug_net_nntp,\n+\t\t    \"protocol=s\" => \\$email_protocol,\n \t\t    \"identity=s\" => \\$identity,\n \t\t    \"annotate!\" => \\$annotate,\n \t\t    \"compose\" => \\$compose,\n \t\t    \"quiet\" => \\$quiet,\n-\t\t    \"cc-cmd=s\" => \\$cc_cmd,\n \t\t    \"suppress-from!\" => \\$suppress_from,\n \t\t    \"suppress-cc=s\" => \\@suppress_cc,\n \t\t    \"signed-off-cc|signed-off-by-cc!\" => \\$signed_off_by_cc,\n@@ -390,6 +418,24 @@ foreach my $setting (values %config_bool_settings) {\n \t${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]}));\n }\n \n+unless ($email_protocol eq 'smtp' || $email_protocol eq 'nntp') {\n+\tdie \"Unsupported protocol: $email_protocol\";\n+}\n+\n+# Transport specific setup\n+my ($email_authuser, $email_authpass);\n+if ($email_protocol eq 'nntp') {\n+    $email_authuser = $nntp_authuser;\n+    $email_authuser = $nntp_authuser;\n+    @initial_to = @initial_cc = @bcclist = ();\n+    $to_cmd = $cc_cmd = undef;\n+    $no_cc = $no_bcc = 1;\n+} else {\n+    $email_authuser = $smtp_authuser;\n+    $email_authpass = $smtp_authpass;\n+    $newsgroups_cmd = undef;\n+}\n+\n # 'default' encryption is none -- this only prevents a warning\n $smtp_encryption = '' unless (defined $smtp_encryption);\n \n@@ -668,8 +714,8 @@ EOT\n \t\t} elsif (/^From:\\s*(.+)\\s*$/i) {\n \t\t\t$sender = $1;\n \t\t\tnext;\n-\t\t} elsif (/^(?:To|Cc|Bcc):/i) {\n-\t\t\tprint \"To/Cc/Bcc fields are not interpreted yet, they have been ignored\\n\";\n+\t\t} elsif (/^(?:To|Cc|Bcc|Newsgroup):/i) {\n+\t\t\tprint \"To/Cc/Bcc/Newsgroup fields are not interpreted yet, they have been ignored\\n\";\n \t\t\tnext;\n \t\t}\n \t\tprint $c2 $_;\n@@ -761,12 +807,21 @@ if (!defined $sender) {\n }\n \n my $prompting = 0;\n-if (!@initial_to && !defined $to_cmd) {\n+\n+if ($email_protocol eq 'smtp' && !@initial_to && !defined $to_cmd) {\n \tmy $to = ask(\"Who should the emails be sent to (if any)? \",\n \t\t     default => \"\",\n \t\t     valid_re => qr/\\@.*\\./, confirm_only => 1);\n \tpush @initial_to, parse_address_line($to) if defined $to; # sanitized/validated later\n \t$prompting++;\n+} elsif ($email_protocol eq 'nntp' &&\n+\t !@initial_newsgroups &&\n+\t !defined $newsgroups_cmd) {\n+\tmy $newsgroup = ask(\"Which newsgroups should the message be sent to (if any)? \",\n+\t\t     default => \"\",\n+\t\t     valid_re => qr/[\\x20-\\x7f]+/, confirm_only => 1);\n+\tpush @initial_newsgroups, $newsgroup if defined $newsgroup; # sanitized/validated later\n+\t$prompting++;\n }\n \n sub expand_aliases {\n@@ -802,7 +857,7 @@ if (defined $initial_reply_to) {\n \t$initial_reply_to = \"<$initial_reply_to>\" if $initial_reply_to ne '';\n }\n \n-if (!defined $smtp_server) {\n+if ($email_protocol eq 'smtp' && !defined $smtp_server) {\n \tforeach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {\n \t\tif (-x $_) {\n \t\t\t$smtp_server = $_;\n@@ -1048,41 +1103,56 @@ sub maildomain {\n \treturn maildomain_net() || maildomain_mta() || 'localhost.localdomain';\n }\n \n-sub smtp_host_string {\n-\tif (defined $smtp_server_port) {\n-\t\treturn \"$smtp_server:$smtp_server_port\";\n+sub email_host_string {\n+\tif ($email_protocol eq 'nntp') {\n+\t\tif (defined $nntp_server_port) {\n+\t\t\treturn \"$nntp_server:$nntp_server_port\";\n+\t\t} else {\n+\t\t\treturn $nntp_server;\n+\t\t}\n+\n \t} else {\n-\t\treturn $smtp_server;\n+\t\tif (defined $smtp_server_port) {\n+\t\t\treturn \"$smtp_server:$smtp_server_port\";\n+\t\t} else {\n+\t\t\treturn $smtp_server;\n+\t\t}\n \t}\n }\n \n # Returns 1 if authentication succeeded or was not necessary\n # (smtp_user was not specified), and 0 otherwise.\n \n-sub smtp_auth_maybe {\n-\tif (!defined $smtp_authuser || $auth) {\n+sub email_auth_maybe {\n+\tif (!defined $email_authuser || $auth) {\n \t\treturn 1;\n \t}\n \n \t# Workaround AUTH PLAIN/LOGIN interaction defect\n \t# with Authen::SASL::Cyrus\n-\teval {\n-\t\trequire Authen::SASL;\n-\t\tAuthen::SASL->import(qw(Perl));\n-\t};\n+\tif ($email_protocol eq 'smtp') {\n+\t\teval {\n+\t\t\trequire Authen::SASL;\n+\t\t\tAuthen::SASL->import(qw(Perl));\n+\t\t};\n+\t}\n \n \t# TODO: Authentication may fail not because credentials were\n \t# invalid but due to other reasons, in which we should not\n \t# reject credentials.\n \t$auth = Git::credential({\n-\t\t'protocol' => 'smtp',\n-\t\t'host' => smtp_host_string(),\n-\t\t'username' => $smtp_authuser,\n+\t\t'protocol' => $email_protocol,\n+\t\t'host' => email_host_string(),\n+\t\t'username' => $email_authuser,\n \t\t# if there's no password, \"git credential fill\" will\n \t\t# give us one, otherwise it'll just pass this one.\n-\t\t'password' => $smtp_authpass\n+\t\t'password' => $email_authpass\n \t}, sub {\n \t\tmy $cred = shift;\n+\t\tif ($email_protocol eq 'nntp') {\n+\t\t\treturn !!$nntp->authinfo($cred->{'username'},\n+\t\t\t\t\t\t $cred->{'password'});\n+\t\t}\n \t\treturn !!$smtp->auth($cred->{'username'}, $cred->{'password'});\n \t});\n \n@@ -1099,7 +1169,7 @@ sub send_message {\n \t\t      not grep { $cc eq $_ || $_ =~ /<\\Q${cc}\\E>$/ } @recipients\n \t\t    }\n \t       @cc);\n-\tmy $to = join (\",\\n\\t\", @recipients);\n+\tmy $to = join (\",\\n\\t\", (($email_protocol eq 'nntp') ? @newsgroups : @recipients));\n \t@recipients = unique_email_list(@recipients,@cc,@bcclist);\n \t@recipients = (map { extract_valid_address_or_die($_) } @recipients);\n \tmy $date = format_2822_time($time++);\n@@ -1117,12 +1187,17 @@ sub send_message {\n \tmake_message_id() unless defined($message_id);\n \n \tmy $header = \"From: $sanitized_sender\n-To: $to${ccline}\n Subject: $subject\n Date: $date\n Message-Id: $message_id\n X-Mailer: git-send-email $gitversion\n \";\n+\tif ($email_protocol eq 'nntp') {\n+\t\t$header = \"Newsgroups: $to\\n\" . $header;\n+\t} else {\n+\t\t$header = \"To: $to${ccline}\\n\" . $header;\n+\t}\n+\n \tif ($reply_to) {\n \n \t\t$header .= \"In-Reply-To: $reply_to\\n\";\n@@ -1174,6 +1249,18 @@ X-Mailer: git-send-email $gitversion\n \n \tif ($dry_run) {\n \t\t# We don't want to send the email.\n+\t} elsif ($email_protocol eq 'nntp') {\n+\t\tif (!defined $nntp_server) {\n+\t\t\tdie \"The requires NNTP server is not properly defined.\"\n+\t\t}\n+\t\trequire Net::NNTP;\n+\t\t$nntp =  Net::NNTP->new(email_host_string(),\n+\t\t                        Debug => $debug_net_nntp);\n+\t\temail_auth_maybe or die $nntp->message;\n+\t\t$nntp->post or die $nntp->message;\n+\t\t$nntp->datasend(\"$header\\n$message\") or die $nntp->message;\n+\t\t$nntp->dataend() or die $nntp->message;\n+\t\t$nntp->code eq \"240\" or die \"Failed to send $subject\\n\".$nntp->message;\n \t} elsif ($smtp_server =~ m#^/#) {\n \t\tmy $pid = open my $sm, '|-';\n \t\tdefined $pid or die $!;\n@@ -1195,11 +1282,10 @@ X-Mailer: git-send-email $gitversion\n \t\t\t$smtp ||= Net::SMTP::SSL->new($smtp_server,\n \t\t\t\t\t\t      Hello => $smtp_domain,\n \t\t\t\t\t\t      Port => $smtp_server_port);\n-\t\t}\n-\t\telse {\n+\t\t} else {\n \t\t\trequire Net::SMTP;\n \t\t\t$smtp_domain ||= maildomain();\n-\t\t\t$smtp ||= Net::SMTP->new(smtp_host_string(),\n+\t\t\t$smtp ||= Net::SMTP->new(email_host_string(),\n \t\t\t\t\t\t Hello => $smtp_domain,\n \t\t\t\t\t\t Debug => $debug_net_smtp);\n \t\t\tif ($smtp_encryption eq 'tls' && $smtp) {\n@@ -1227,7 +1313,7 @@ X-Mailer: git-send-email $gitversion\n \t\t\t    defined $smtp_server_port ? \" port=$smtp_server_port\" : \"\";\n \t\t}\n \n-\t\tsmtp_auth_maybe or die $smtp->message;\n+\t\temail_auth_maybe or die $smtp->message;\n \n \t\t$smtp->mail( $raw_from ) or die $smtp->message;\n \t\t$smtp->to( @recipients ) or die $smtp->message;\n@@ -1240,7 +1326,9 @@ X-Mailer: git-send-email $gitversion\n \t\tprintf (($dry_run ? \"Dry-\" : \"\").\"Sent %s\\n\", $subject);\n \t} else {\n \t\tprint (($dry_run ? \"Dry-\" : \"\").\"OK. Log says:\\n\");\n-\t\tif ($smtp_server !~ m#^/#) {\n+\t\tif ($email_protocol eq 'nntp') {\n+\t\t\tprint \"Server: $nntp_server\\n\";\n+\t\t} elsif ($smtp_server !~ m#^/#) {\n \t\t\tprint \"Server: $smtp_server\\n\";\n \t\t\tprint \"MAIL FROM:<$raw_from>\\n\";\n \t\t\tforeach my $entry (@recipients) {\n@@ -1250,9 +1338,10 @@ X-Mailer: git-send-email $gitversion\n \t\t\tprint \"Sendmail: $smtp_server \".join(' ',@sendmail_parameters).\"\\n\";\n \t\t}\n \t\tprint $header, \"\\n\";\n-\t\tif ($smtp) {\n-\t\t\tprint \"Result: \", $smtp->code, ' ',\n-\t\t\t\t($smtp->message =~ /\\n([^\\n]+\\n)$/s), \"\\n\";\n+\t\tmy $transport = $nntp || $smtp;\n+\t\tif ($transport) {\n+\t\t\tprint \"Result: \", $transport->code, ' ',\n+\t\t\t\t($transport->message =~ /\\n([^\\n]+\\n)$/s), \"\\n\";\n \t\t} else {\n \t\t\tprint \"Result: OK\\n\";\n \t\t}\n@@ -1383,6 +1472,9 @@ foreach my $t (@files) {\n \t}\n \tclose $fh;\n \n+\tpush @newsgroups, recipients_cmd(\"newsgroups-cmd\", \"newsgroups\",\n+\t\t\t\t\t $newsgroups_cmd, $t)\n+\t\tif defined $newsgroups_cmd;\n \tpush @to, recipients_cmd(\"to-cmd\", \"to\", $to_cmd, $t)\n \t\tif defined $to_cmd;\n \tpush @cc, recipients_cmd(\"cc-cmd\", \"cc\", $cc_cmd, $t)\n@@ -1430,6 +1522,7 @@ foreach my $t (@files) {\n \t@to = validate_address_list(sanitize_address_list(@to));\n \t@cc = validate_address_list(sanitize_address_list(@cc));\n \n+\t@newsgroups = (@initial_newsgroups, @newsgroups);\n \t@to = (@initial_to, @to);\n \t@cc = (@initial_cc, @cc);\n \n@@ -1479,6 +1572,7 @@ sub cleanup_compose_files {\n }\n \n $smtp->quit if $smtp;\n+$nntp->quit if $nntp;\n \n sub unique_email_list {\n \tmy %seen;\n-- \n1.7.9.5\n"},{"id":"215233","messageId":"7vobd5l277.fsf@alter.siamese.dyndns.org","threadId":"33579","inReplyTo":"1366715634-21790-1-git-send-email-l.stelmach@samsung.com","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-23T15:02:52Z","receivedAt":"2013-04-23T15:02:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Łukasz Stelmach <l.stelmach@samsung.com> writes:\n\n> Enable sending patches to NNTP servers (Usenet, Gmane).\n> ---\n>\n> The patch implements support for sending messages to groups on NNTP serviers.\n\nCute.\n\nA Perl guru might want to encapsulate the differences between $smtp\nand $nntp codepaths into two Perl modules, but it looks like a good\nstarting point.\n\n> The patch does not (attempts not to) change the default behavior i.e. to use sendmail\n> and/or Net::SMTP. To use NNTP one needs to configure the server (see the help message)\n> and protocol (\"--protocol nntp\"). Then after giving --newsgroups the\n> message will be sent via NNTP. Like this one:\n>\n> perl git-send-email.perl --protocol nntp --newsgroups gmane.comp.version-control.git --nntp-server news.gmane.org 0001-send-email-support-NNTP.patch\n>\n>  git-send-email.perl |  156 +++++++++++++++++++++++++++++++++++++++++----------\n>  1 file changed, 125 insertions(+), 31 deletions(-)\n>\n> diff --git a/git-send-email.perl b/git-send-email.perl\n> index bd13cc8..0356635 100755\n> --- a/git-send-email.perl\n> +++ b/git-send-email.perl\n> @@ -54,12 +54,14 @@ git send-email [options] <file | directory | rev-list options >\n>      --[no-]bcc              <str>  * Email Bcc:\n>      --subject               <str>  * Email \"Subject:\"\n>      --in-reply-to           <str>  * Email \"In-Reply-To:\"\n> +    --newsgroups            <str>  * NNTP Newsgroups:\n>      --[no-]annotate                * Review each patch that will be sent in an editor.\n>      --compose                      * Open an editor for introduction.\n>      --compose-encoding      <str>  * Encoding to assume for introduction.\n>      --8bit-encoding         <str>  * Encoding to assume 8bit mails if undeclared\n>  \n>    Sending:\n> +    --protocol              <str>  * 'smtp' or 'nntp'. Default 'smtp'.\n>      --envelope-sender       <str>  * Email envelope sender.\n>      --smtp-server       <str:int>  * Outgoing SMTP server to use. The port\n>                                       is optional. Default 'localhost'.\n> @@ -71,6 +73,12 @@ git send-email [options] <file | directory | rev-list options >\n>      --smtp-ssl                     * Deprecated. Use '--smtp-encryption ssl'.\n>      --smtp-domain           <str>  * The domain name sent to HELO/EHLO handshake\n>      --smtp-debug            <0|1>  * Disable, enable Net::SMTP debug.\n> +    --nntp-server       <str:int>  * Outgoing NNTP server to use. The port\n> +                                     is optional.\n> +    --nntp-server-port      <int>  * Outgoing NNTP server port.\n> +    --nntp-user             <str>  * Username for NNTP AUTHINFO.\n> +    --nntp-pass             <str>  * Password for NNTP AUTHINFO.\n> +    --nntp-debug            <0|1>  * Disable, enable Net::NNTP debug.\n>  \n>    Automating:\n>      --identity              <str>  * Use the sendemail.<id> options.\n> @@ -138,12 +146,14 @@ sub format_2822_time {\n>  my $have_email_valid = eval { require Email::Valid; 1 };\n>  my $have_mail_address = eval { require Mail::Address; 1 };\n>  my $smtp;\n> +my $nntp;\n>  my $auth;\n>  \n>  # Variables we fill in automatically, or via prompting:\n>  my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,\n>  \t$initial_reply_to,$initial_subject,@files,\n> -\t$author,$sender,$smtp_authpass,$annotate,$compose,$time);\n> +\t$author,$sender,$smtp_authpass,$annotate,$compose,$time,\n> +\t@initial_newsgroups, @newsgroups);\n>  \n>  my $envelope_sender;\n>  \n> @@ -192,7 +202,9 @@ sub do_edit {\n>  \n>  # Variables with corresponding config settings\n>  my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc);\n> -my ($to_cmd, $cc_cmd);\n> +my ($to_cmd, $cc_cmd, $newsgroups_cmd);\n> +my ($email_protocol) = 'smtp';\n> +my ($nntp_server, $nntp_server_port, $nntp_authuser, $nntp_authpass);\n>  my ($smtp_server, $smtp_server_port, @smtp_server_options);\n>  my ($smtp_authuser, $smtp_encryption);\n>  my ($identity, $aliasfiletype, @alias_files, $smtp_domain);\n> @@ -202,6 +214,7 @@ my ($auto_8bit_encoding);\n>  my ($compose_encoding);\n>  \n>  my ($debug_net_smtp) = 0;\t\t# Net::SMTP, see send_message()\n> +my ($debug_net_nntp) = 0;\t\t# Net::NNTP, see send_message()\n>  \n>  my $not_set_by_user = \"true but not set by the user\";\n>  \n> @@ -235,6 +248,13 @@ my %config_settings = (\n>      \"from\" => \\$sender,\n>      \"assume8bitencoding\" => \\$auto_8bit_encoding,\n>      \"composeencoding\" => \\$compose_encoding,\n> +    \"nntpserver\" => \\$nntp_server,\n> +    \"nntpserverport\" => \\$nntp_server_port,\n> +    \"nntpuser\" => \\$nntp_authuser,\n> +    \"nntppass\" => \\$nntp_authpass,\n> +    \"protocol\" => \\$email_protocol,\n> +    \"newsgroups\" => \\@initial_newsgroups,\n> +    \"newsgroupscmd\" => \\$newsgroups_cmd,\n>  );\n>  \n>  my %config_path_settings = (\n> @@ -291,6 +311,7 @@ my $rc = GetOptions(\"h\" => \\$help,\n>  \t\t    \"to-cmd=s\" => \\$to_cmd,\n>  \t\t    \"no-to\" => \\$no_to,\n>  \t\t    \"cc=s\" => \\@initial_cc,\n> +\t\t    \"cc-cmd=s\" => \\$cc_cmd,\n>  \t\t    \"no-cc\" => \\$no_cc,\n>  \t\t    \"bcc=s\" => \\@bcclist,\n>  \t\t    \"no-bcc\" => \\$no_bcc,\n> @@ -304,11 +325,18 @@ my $rc = GetOptions(\"h\" => \\$help,\n>  \t\t    \"smtp-encryption=s\" => \\$smtp_encryption,\n>  \t\t    \"smtp-debug:i\" => \\$debug_net_smtp,\n>  \t\t    \"smtp-domain:s\" => \\$smtp_domain,\n> +\t\t    \"newsgroups=s\" => \\@initial_newsgroups,\n> +\t\t    \"newsgroups-cmd\" => \\$newsgroups_cmd,\n> +\t\t    \"nntp-server=s\" => \\$nntp_server,\n> +\t\t    \"nntp-server-port=s\" => \\$nntp_server_port,\n> +\t\t    \"nntp-user=s\" => \\$nntp_authuser,\n> +\t\t    \"nntp-pass:s\" => \\$nntp_authpass,\n> +\t\t    \"nntp-debug:i\" => \\$debug_net_nntp,\n> +\t\t    \"protocol=s\" => \\$email_protocol,\n>  \t\t    \"identity=s\" => \\$identity,\n>  \t\t    \"annotate!\" => \\$annotate,\n>  \t\t    \"compose\" => \\$compose,\n>  \t\t    \"quiet\" => \\$quiet,\n> -\t\t    \"cc-cmd=s\" => \\$cc_cmd,\n>  \t\t    \"suppress-from!\" => \\$suppress_from,\n>  \t\t    \"suppress-cc=s\" => \\@suppress_cc,\n>  \t\t    \"signed-off-cc|signed-off-by-cc!\" => \\$signed_off_by_cc,\n> @@ -390,6 +418,24 @@ foreach my $setting (values %config_bool_settings) {\n>  \t${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]}));\n>  }\n>  \n> +unless ($email_protocol eq 'smtp' || $email_protocol eq 'nntp') {\n> +\tdie \"Unsupported protocol: $email_protocol\";\n> +}\n> +\n> +# Transport specific setup\n> +my ($email_authuser, $email_authpass);\n> +if ($email_protocol eq 'nntp') {\n> +    $email_authuser = $nntp_authuser;\n> +    $email_authuser = $nntp_authuser;\n> +    @initial_to = @initial_cc = @bcclist = ();\n> +    $to_cmd = $cc_cmd = undef;\n> +    $no_cc = $no_bcc = 1;\n> +} else {\n> +    $email_authuser = $smtp_authuser;\n> +    $email_authpass = $smtp_authpass;\n> +    $newsgroups_cmd = undef;\n> +}\n> +\n>  # 'default' encryption is none -- this only prevents a warning\n>  $smtp_encryption = '' unless (defined $smtp_encryption);\n>  \n> @@ -668,8 +714,8 @@ EOT\n>  \t\t} elsif (/^From:\\s*(.+)\\s*$/i) {\n>  \t\t\t$sender = $1;\n>  \t\t\tnext;\n> -\t\t} elsif (/^(?:To|Cc|Bcc):/i) {\n> -\t\t\tprint \"To/Cc/Bcc fields are not interpreted yet, they have been ignored\\n\";\n> +\t\t} elsif (/^(?:To|Cc|Bcc|Newsgroup):/i) {\n> +\t\t\tprint \"To/Cc/Bcc/Newsgroup fields are not interpreted yet, they have been ignored\\n\";\n>  \t\t\tnext;\n>  \t\t}\n>  \t\tprint $c2 $_;\n> @@ -761,12 +807,21 @@ if (!defined $sender) {\n>  }\n>  \n>  my $prompting = 0;\n> -if (!@initial_to && !defined $to_cmd) {\n> +\n> +if ($email_protocol eq 'smtp' && !@initial_to && !defined $to_cmd) {\n>  \tmy $to = ask(\"Who should the emails be sent to (if any)? \",\n>  \t\t     default => \"\",\n>  \t\t     valid_re => qr/\\@.*\\./, confirm_only => 1);\n>  \tpush @initial_to, parse_address_line($to) if defined $to; # sanitized/validated later\n>  \t$prompting++;\n> +} elsif ($email_protocol eq 'nntp' &&\n> +\t !@initial_newsgroups &&\n> +\t !defined $newsgroups_cmd) {\n> +\tmy $newsgroup = ask(\"Which newsgroups should the message be sent to (if any)? \",\n> +\t\t     default => \"\",\n> +\t\t     valid_re => qr/[\\x20-\\x7f]+/, confirm_only => 1);\n> +\tpush @initial_newsgroups, $newsgroup if defined $newsgroup; # sanitized/validated later\n> +\t$prompting++;\n>  }\n>  \n>  sub expand_aliases {\n> @@ -802,7 +857,7 @@ if (defined $initial_reply_to) {\n>  \t$initial_reply_to = \"<$initial_reply_to>\" if $initial_reply_to ne '';\n>  }\n>  \n> -if (!defined $smtp_server) {\n> +if ($email_protocol eq 'smtp' && !defined $smtp_server) {\n>  \tforeach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {\n>  \t\tif (-x $_) {\n>  \t\t\t$smtp_server = $_;\n> @@ -1048,41 +1103,56 @@ sub maildomain {\n>  \treturn maildomain_net() || maildomain_mta() || 'localhost.localdomain';\n>  }\n>  \n> -sub smtp_host_string {\n> -\tif (defined $smtp_server_port) {\n> -\t\treturn \"$smtp_server:$smtp_server_port\";\n> +sub email_host_string {\n> +\tif ($email_protocol eq 'nntp') {\n> +\t\tif (defined $nntp_server_port) {\n> +\t\t\treturn \"$nntp_server:$nntp_server_port\";\n> +\t\t} else {\n> +\t\t\treturn $nntp_server;\n> +\t\t}\n> +\n>  \t} else {\n> -\t\treturn $smtp_server;\n> +\t\tif (defined $smtp_server_port) {\n> +\t\t\treturn \"$smtp_server:$smtp_server_port\";\n> +\t\t} else {\n> +\t\t\treturn $smtp_server;\n> +\t\t}\n>  \t}\n>  }\n>  \n>  # Returns 1 if authentication succeeded or was not necessary\n>  # (smtp_user was not specified), and 0 otherwise.\n>  \n> -sub smtp_auth_maybe {\n> -\tif (!defined $smtp_authuser || $auth) {\n> +sub email_auth_maybe {\n> +\tif (!defined $email_authuser || $auth) {\n>  \t\treturn 1;\n>  \t}\n>  \n>  \t# Workaround AUTH PLAIN/LOGIN interaction defect\n>  \t# with Authen::SASL::Cyrus\n> -\teval {\n> -\t\trequire Authen::SASL;\n> -\t\tAuthen::SASL->import(qw(Perl));\n> -\t};\n> +\tif ($email_protocol eq 'smtp') {\n> +\t\teval {\n> +\t\t\trequire Authen::SASL;\n> +\t\t\tAuthen::SASL->import(qw(Perl));\n> +\t\t};\n> +\t}\n>  \n>  \t# TODO: Authentication may fail not because credentials were\n>  \t# invalid but due to other reasons, in which we should not\n>  \t# reject credentials.\n>  \t$auth = Git::credential({\n> -\t\t'protocol' => 'smtp',\n> -\t\t'host' => smtp_host_string(),\n> -\t\t'username' => $smtp_authuser,\n> +\t\t'protocol' => $email_protocol,\n> +\t\t'host' => email_host_string(),\n> +\t\t'username' => $email_authuser,\n>  \t\t# if there's no password, \"git credential fill\" will\n>  \t\t# give us one, otherwise it'll just pass this one.\n> -\t\t'password' => $smtp_authpass\n> +\t\t'password' => $email_authpass\n>  \t}, sub {\n>  \t\tmy $cred = shift;\n> +\t\tif ($email_protocol eq 'nntp') {\n> +\t\t\treturn !!$nntp->authinfo($cred->{'username'},\n> +\t\t\t\t\t\t $cred->{'password'});\n> +\t\t}\n>  \t\treturn !!$smtp->auth($cred->{'username'}, $cred->{'password'});\n>  \t});\n>  \n> @@ -1099,7 +1169,7 @@ sub send_message {\n>  \t\t      not grep { $cc eq $_ || $_ =~ /<\\Q${cc}\\E>$/ } @recipients\n>  \t\t    }\n>  \t       @cc);\n> -\tmy $to = join (\",\\n\\t\", @recipients);\n> +\tmy $to = join (\",\\n\\t\", (($email_protocol eq 'nntp') ? @newsgroups : @recipients));\n>  \t@recipients = unique_email_list(@recipients,@cc,@bcclist);\n>  \t@recipients = (map { extract_valid_address_or_die($_) } @recipients);\n>  \tmy $date = format_2822_time($time++);\n> @@ -1117,12 +1187,17 @@ sub send_message {\n>  \tmake_message_id() unless defined($message_id);\n>  \n>  \tmy $header = \"From: $sanitized_sender\n> -To: $to${ccline}\n>  Subject: $subject\n>  Date: $date\n>  Message-Id: $message_id\n>  X-Mailer: git-send-email $gitversion\n>  \";\n> +\tif ($email_protocol eq 'nntp') {\n> +\t\t$header = \"Newsgroups: $to\\n\" . $header;\n> +\t} else {\n> +\t\t$header = \"To: $to${ccline}\\n\" . $header;\n> +\t}\n> +\n>  \tif ($reply_to) {\n>  \n>  \t\t$header .= \"In-Reply-To: $reply_to\\n\";\n> @@ -1174,6 +1249,18 @@ X-Mailer: git-send-email $gitversion\n>  \n>  \tif ($dry_run) {\n>  \t\t# We don't want to send the email.\n> +\t} elsif ($email_protocol eq 'nntp') {\n> +\t\tif (!defined $nntp_server) {\n> +\t\t\tdie \"The requires NNTP server is not properly defined.\"\n> +\t\t}\n> +\t\trequire Net::NNTP;\n> +\t\t$nntp =  Net::NNTP->new(email_host_string(),\n> +\t\t                        Debug => $debug_net_nntp);\n> +\t\temail_auth_maybe or die $nntp->message;\n> +\t\t$nntp->post or die $nntp->message;\n> +\t\t$nntp->datasend(\"$header\\n$message\") or die $nntp->message;\n> +\t\t$nntp->dataend() or die $nntp->message;\n> +\t\t$nntp->code eq \"240\" or die \"Failed to send $subject\\n\".$nntp->message;\n>  \t} elsif ($smtp_server =~ m#^/#) {\n>  \t\tmy $pid = open my $sm, '|-';\n>  \t\tdefined $pid or die $!;\n> @@ -1195,11 +1282,10 @@ X-Mailer: git-send-email $gitversion\n>  \t\t\t$smtp ||= Net::SMTP::SSL->new($smtp_server,\n>  \t\t\t\t\t\t      Hello => $smtp_domain,\n>  \t\t\t\t\t\t      Port => $smtp_server_port);\n> -\t\t}\n> -\t\telse {\n> +\t\t} else {\n>  \t\t\trequire Net::SMTP;\n>  \t\t\t$smtp_domain ||= maildomain();\n> -\t\t\t$smtp ||= Net::SMTP->new(smtp_host_string(),\n> +\t\t\t$smtp ||= Net::SMTP->new(email_host_string(),\n>  \t\t\t\t\t\t Hello => $smtp_domain,\n>  \t\t\t\t\t\t Debug => $debug_net_smtp);\n>  \t\t\tif ($smtp_encryption eq 'tls' && $smtp) {\n> @@ -1227,7 +1313,7 @@ X-Mailer: git-send-email $gitversion\n>  \t\t\t    defined $smtp_server_port ? \" port=$smtp_server_port\" : \"\";\n>  \t\t}\n>  \n> -\t\tsmtp_auth_maybe or die $smtp->message;\n> +\t\temail_auth_maybe or die $smtp->message;\n>  \n>  \t\t$smtp->mail( $raw_from ) or die $smtp->message;\n>  \t\t$smtp->to( @recipients ) or die $smtp->message;\n> @@ -1240,7 +1326,9 @@ X-Mailer: git-send-email $gitversion\n>  \t\tprintf (($dry_run ? \"Dry-\" : \"\").\"Sent %s\\n\", $subject);\n>  \t} else {\n>  \t\tprint (($dry_run ? \"Dry-\" : \"\").\"OK. Log says:\\n\");\n> -\t\tif ($smtp_server !~ m#^/#) {\n> +\t\tif ($email_protocol eq 'nntp') {\n> +\t\t\tprint \"Server: $nntp_server\\n\";\n> +\t\t} elsif ($smtp_server !~ m#^/#) {\n>  \t\t\tprint \"Server: $smtp_server\\n\";\n>  \t\t\tprint \"MAIL FROM:<$raw_from>\\n\";\n>  \t\t\tforeach my $entry (@recipients) {\n> @@ -1250,9 +1338,10 @@ X-Mailer: git-send-email $gitversion\n>  \t\t\tprint \"Sendmail: $smtp_server \".join(' ',@sendmail_parameters).\"\\n\";\n>  \t\t}\n>  \t\tprint $header, \"\\n\";\n> -\t\tif ($smtp) {\n> -\t\t\tprint \"Result: \", $smtp->code, ' ',\n> -\t\t\t\t($smtp->message =~ /\\n([^\\n]+\\n)$/s), \"\\n\";\n> +\t\tmy $transport = $nntp || $smtp;\n> +\t\tif ($transport) {\n> +\t\t\tprint \"Result: \", $transport->code, ' ',\n> +\t\t\t\t($transport->message =~ /\\n([^\\n]+\\n)$/s), \"\\n\";\n>  \t\t} else {\n>  \t\t\tprint \"Result: OK\\n\";\n>  \t\t}\n> @@ -1383,6 +1472,9 @@ foreach my $t (@files) {\n>  \t}\n>  \tclose $fh;\n>  \n> +\tpush @newsgroups, recipients_cmd(\"newsgroups-cmd\", \"newsgroups\",\n> +\t\t\t\t\t $newsgroups_cmd, $t)\n> +\t\tif defined $newsgroups_cmd;\n>  \tpush @to, recipients_cmd(\"to-cmd\", \"to\", $to_cmd, $t)\n>  \t\tif defined $to_cmd;\n>  \tpush @cc, recipients_cmd(\"cc-cmd\", \"cc\", $cc_cmd, $t)\n> @@ -1430,6 +1522,7 @@ foreach my $t (@files) {\n>  \t@to = validate_address_list(sanitize_address_list(@to));\n>  \t@cc = validate_address_list(sanitize_address_list(@cc));\n>  \n> +\t@newsgroups = (@initial_newsgroups, @newsgroups);\n>  \t@to = (@initial_to, @to);\n>  \t@cc = (@initial_cc, @cc);\n>  \n> @@ -1479,6 +1572,7 @@ sub cleanup_compose_files {\n>  }\n>  \n>  $smtp->quit if $smtp;\n> +$nntp->quit if $nntp;\n>  \n>  sub unique_email_list {\n>  \tmy %seen;\n"},{"id":"215290","messageId":"CAPig+cT18z7Hs70XMF99ACOs5cy2S=FTapjQO=Mb+EMYc=6hJw@mail.gmail.com","threadId":"33579","inReplyTo":"1366715634-21790-1-git-send-email-l.stelmach@samsung.com","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-04-24T07:19:43Z","receivedAt":"2013-04-24T07:19:43Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Tue, Apr 23, 2013 at 7:13 AM, Łukasz Stelmach <l.stelmach@samsung.com> wrote:\n> Enable sending patches to NNTP servers (Usenet, Gmane).\n> ---\n> diff --git a/git-send-email.perl b/git-send-email.perl\n> index bd13cc8..0356635 100755\n> --- a/git-send-email.perl\n> +++ b/git-send-email.perl\n> @@ -1174,6 +1249,18 @@ X-Mailer: git-send-email $gitversion\n>\n>         if ($dry_run) {\n>                 # We don't want to send the email.\n> +       } elsif ($email_protocol eq 'nntp') {\n> +               if (!defined $nntp_server) {\n> +                       die \"The requires NNTP server is not properly defined.\"\n\ns/requires/required/\n\n> +               }\n> +               require Net::NNTP;\n> +               $nntp =  Net::NNTP->new(email_host_string(),\n> +                                       Debug => $debug_net_nntp);\n> +               email_auth_maybe or die $nntp->message;\n> +               $nntp->post or die $nntp->message;\n> +               $nntp->datasend(\"$header\\n$message\") or die $nntp->message;\n> +               $nntp->dataend() or die $nntp->message;\n> +               $nntp->code eq \"240\" or die \"Failed to send $subject\\n\".$nntp->message;\n>         } elsif ($smtp_server =~ m#^/#) {\n>                 my $pid = open my $sm, '|-';\n>                 defined $pid or die $!;\n"},{"id":"215291","messageId":"87y5c875dj.fsf@samsung.com","threadId":"33579","inReplyTo":"CAPig+cT18z7Hs70XMF99ACOs5cy2S=FTapjQO=Mb+EMYc=6hJw@mail.gmail.com","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Łukasz Stelmach","fromEmail":"l.stelmach@samsung.com","sentAt":"2013-04-24T07:30:16Z","receivedAt":"2013-04-24T07:30:16Z","isPatch":true,"sender":{"key":"l.stelmach@samsung.com","avatar":"https://gravatar.com/avatar/b5f9262ad19b1b6f1e74b8eba816455e059742e8d980fdefa9321976071642fc?d=mp&s=160"},"body":"It was <2013-04-24 śro 09:19>, when Eric Sunshine wrote:\n> On Tue, Apr 23, 2013 at 7:13 AM, Łukasz Stelmach <l.stelmach@samsung.com> wrote:\n>> Enable sending patches to NNTP servers (Usenet, Gmane).\n>> ---\n>> diff --git a/git-send-email.perl b/git-send-email.perl\n>> index bd13cc8..0356635 100755\n>> --- a/git-send-email.perl\n>> +++ b/git-send-email.perl\n>> @@ -1174,6 +1249,18 @@ X-Mailer: git-send-email $gitversion\n>>\n>>         if ($dry_run) {\n>>                 # We don't want to send the email.\n>> +       } elsif ($email_protocol eq 'nntp') {\n>> +               if (!defined $nntp_server) {\n>> +                       die \"The requires NNTP server is not properly defined.\"\n>\n> s/requires/required/\n\nDone. Waiting for more comments.\n\n-- \nŁukasz Stelmach\nSoftware wizzard\nSamsung Poland R&D Center\n\nAl. Armii Ludowej 26, 00-609 Warszawa\nhttp://www.rd.samsung.pl\n"},{"id":"215292","messageId":"87txmw75bb.fsf@samsung.com","threadId":"33579","inReplyTo":"7vobd5l277.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Łukasz Stelmach","fromEmail":"l.stelmach@samsung.com","sentAt":"2013-04-24T07:31:36Z","receivedAt":"2013-04-24T07:31:36Z","isPatch":true,"sender":{"key":"l.stelmach@samsung.com","avatar":"https://gravatar.com/avatar/b5f9262ad19b1b6f1e74b8eba816455e059742e8d980fdefa9321976071642fc?d=mp&s=160"},"body":"It was <2013-04-23 wto 17:02>, when Junio C Hamano wrote:\n> Łukasz Stelmach <l.stelmach@samsung.com> writes:\n>\n>> Enable sending patches to NNTP servers (Usenet, Gmane).\n>> ---\n>>\n>> The patch implements support for sending messages to groups on NNTP serviers.\n>\n> Cute.\n>\n> A Perl guru might want to encapsulate the differences between $smtp\n> and $nntp codepaths into two Perl modules, but it looks like a good\n> starting point.\n\nYou mean *one* perl module like Git::EmailTransport which hides the\ndifferences.\n\n-- \nŁukasz Stelmach\nSoftware wizzard\nSamsung Poland R&D Center\n\nAl. Armii Ludowej 26, 00-609 Warszawa\nhttp://www.rd.samsung.pl\n"},{"id":"215293","messageId":"87zjwofken.fsf@linux-k42r.v.cablecom.net","threadId":"33579","inReplyTo":"1366715634-21790-1-git-send-email-l.stelmach@samsung.com","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Thomas Rast","fromEmail":"trast@inf.ethz.ch","sentAt":"2013-04-24T07:38:24Z","receivedAt":"2013-04-24T07:38:24Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Łukasz Stelmach <l.stelmach@samsung.com> writes:\n\n> Enable sending patches to NNTP servers (Usenet, Gmane).\n\nI'm surprised Junio didn't mention this: your patch lacks the\nSigned-off-by.\n\n> +\tif ($email_protocol eq 'nntp') {\n> +\t\t$header = \"Newsgroups: $to\\n\" . $header;\n> +\t} else {\n> +\t\t$header = \"To: $to${ccline}\\n\" . $header;\n> +\t}\n\nAre you silently ignoring any Ccs that have been set if you're in NNTP\nmode?\n\nWould it be possible to instead send the Ccs by mail as usual, and only\nthe main message over NNTP?  (You don't need to run off and implement\nthis, but I'm curious how hard you think it would be.)\n\nAt least in the git@vger world with a lot of etiquette surrounding the\nuse of Ccs, NNTP mode isn't very useful if you can't also send Ccs.  But\nmaybe you have another use-case where that is not a problem?\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"215301","messageId":"87bo94720r.fsf@samsung.com","threadId":"33579","inReplyTo":"87zjwofken.fsf@linux-k42r.v.cablecom.net","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Łukasz Stelmach","fromEmail":"l.stelmach@samsung.com","sentAt":"2013-04-24T08:42:44Z","receivedAt":"2013-04-24T08:42:44Z","isPatch":true,"sender":{"key":"l.stelmach@samsung.com","avatar":"https://gravatar.com/avatar/b5f9262ad19b1b6f1e74b8eba816455e059742e8d980fdefa9321976071642fc?d=mp&s=160"},"body":"It was <2013-04-24 śro 09:38>, when Thomas Rast wrote:\n> Łukasz Stelmach <l.stelmach@samsung.com> writes:\n>\n>> Enable sending patches to NNTP servers (Usenet, Gmane).\n>\n> I'm surprised Junio didn't mention this: your patch lacks the\n> Signed-off-by.\n>\n>> +\tif ($email_protocol eq 'nntp') {\n>> +\t\t$header = \"Newsgroups: $to\\n\" . $header;\n>> +\t} else {\n>> +\t\t$header = \"To: $to${ccline}\\n\" . $header;\n>> +\t}\n>\n> Are you silently ignoring any Ccs that have been set if you're in NNTP\n> mode?\n\nYes.\n\n> Would it be possible to instead send the Ccs by mail as usual, and only\n> the main message over NNTP?  (You don't need to run off and implement\n> this, but I'm curious how hard you think it would be.)\n\nCurrently you choose a code path with --protocol. The message is sent\nonly once. It is possible to iterate over To/Cc/Bcc/Newsgroups and\nchoose send it more than once. There are some tiny nasty bits though, I\ndon't know how to handle. For example:\n\n--8<---------------cut here---------------start------------->8---\n@@ -761,12 +807,21 @@ if (!defined $sender) {\n }\n \n my $prompting = 0;\n-if (!@initial_to && !defined $to_cmd) {\n+\n+if ($email_protocol eq 'smtp' && !@initial_to && !defined $to_cmd) {\n \tmy $to = ask(\"Who should the emails be sent to (if any)? \",\n \t\t     default => \"\",\n \t\t     valid_re => qr/\\@.*\\./, confirm_only => 1);\n \tpush @initial_to, parse_address_line($to) if defined $to; # sanitized/validated later\n \t$prompting++;\n+} elsif ($email_protocol eq 'nntp' &&\n+\t !@initial_newsgroups &&\n+\t !defined $newsgroups_cmd) {\n+\tmy $newsgroup = ask(\"Which newsgroups should the message be sent to (if any)? \",\n+\t\t     default => \"\",\n+\t\t     valid_re => qr/[\\x20-\\x7f]+/, confirm_only => 1);\n+\tpush @initial_newsgroups, $newsgroup if defined $newsgroup; # sanitized/validated later\n+\t$prompting++;\n }\n--8<---------------cut here---------------end--------------->8---\n\nHow to ask interactively where to send the message? With protocol set\nearly it is clear what we are trying to do. Any suggestions?\n\nThe other issue is that I am not sure (RFC?) if it is OK to send\nTo/Cc/Bcc headers in a NNTP message. Theoretically they should not break\nthings but...\n\n> At least in the git@vger world with a lot of etiquette surrounding the\n> use of Ccs, NNTP mode isn't very useful if you can't also send Ccs.  But\n> maybe you have another use-case where that is not a problem?\n\nI've sent this patch vi NNTP :) You've got it.\n\n-- \nŁukasz Stelmach\nSoftware wizzard\nSamsung Poland R&D Center\n"},{"id":"215303","messageId":"8761zce0oi.fsf@linux-k42r.v.cablecom.net","threadId":"33579","inReplyTo":"87bo94720r.fsf@samsung.com","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Thomas Rast","fromEmail":"trast@inf.ethz.ch","sentAt":"2013-04-24T09:29:49Z","receivedAt":"2013-04-24T09:29:49Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"l.stelmach@samsung.com (Łukasz Stelmach) writes:\n\n> It was <2013-04-24 śro 09:38>, when Thomas Rast wrote:\n>> Łukasz Stelmach <l.stelmach@samsung.com> writes:\n>>> +\tif ($email_protocol eq 'nntp') {\n>>> +\t\t$header = \"Newsgroups: $to\\n\" . $header;\n>>> +\t} else {\n>>> +\t\t$header = \"To: $to${ccline}\\n\" . $header;\n>>> +\t}\n>>\n>> Are you silently ignoring any Ccs that have been set if you're in NNTP\n>> mode?\n>\n> Yes.\n\nSo wouldn't it be preferable to complain and abort, at the very least if\nthe user explicitly gave some --cc options?\n\nAnd in the documentation that you should write anyway :-), you can state\nthat --protocol nntp does not support Cc or Bcc.  That should be good\nenough.\n\n>> At least in the git@vger world with a lot of etiquette surrounding the\n>> use of Ccs, NNTP mode isn't very useful if you can't also send Ccs.  But\n>> maybe you have another use-case where that is not a problem?\n>\n> I've sent this patch vi NNTP :) You've got it.\n\nHowever, according to the etiquette here you would e.g. send the v2\npatch Cc: everyone who has reviewed the v1 patch.\n\nDon't let that hold you up though.  I'm fine with the feature as long as\nits limitations are clear and documented, and it catches the obvious\nuser errors.  Someone who actually needs NNTP *and* Ccs in the same mail\ncan implement the required support later.\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"215318","messageId":"7vip3bgax9.fsf@alter.siamese.dyndns.org","threadId":"33579","inReplyTo":"87txmw75bb.fsf@samsung.com","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-24T16:17:54Z","receivedAt":"2013-04-24T16:17:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"l.stelmach@samsung.com (Łukasz Stelmach) writes:\n\n> It was <2013-04-23 wto 17:02>, when Junio C Hamano wrote:\n>> Łukasz Stelmach <l.stelmach@samsung.com> writes:\n>>\n>>> Enable sending patches to NNTP servers (Usenet, Gmane).\n>>> ---\n>>>\n>>> The patch implements support for sending messages to groups on NNTP serviers.\n>>\n>> Cute.\n>>\n>> A Perl guru might want to encapsulate the differences between $smtp\n>> and $nntp codepaths into two Perl modules, but it looks like a good\n>> starting point.\n>\n> You mean *one* perl module like Git::EmailTransport which hides the\n> differences.\n\nWhat I meant was one class to handle SMTP and another for NNTP.\n\nYou look at the --protocol option, choose one of these classes, and\ninitialize an instance of the chosen class.\n\nYou can ask the chosen class to instantiate an instance without\nif/else cascade like this:\n\n+\n+# Transport specific setup\n+my ($email_authuser, $email_authpass);\n+if ($email_protocol eq 'nntp') {\n+    $email_authuser = $nntp_authuser;\n+    $email_authuser = $nntp_authuser;\n+    @initial_to = @initial_cc = @bcclist = ();\n+    $to_cmd = $cc_cmd = undef;\n+    $no_cc = $no_bcc = 1;\n+} else {\n+    $email_authuser = $smtp_authuser;\n+    $email_authpass = $smtp_authpass;\n+    $newsgroups_cmd = undef;\n+}\n+\n\nBy asking that instance to ask questions to fill in whatever it\nneeds from the user, you can remove the need of if/elsif cascade\nlike this part in your patch:\n\n+if ($email_protocol eq 'smtp' && !@initial_to && !defined $to_cmd) {\n \tmy $to = ask(\"Who should the emails be sent to (if any)? \",\n \t\t     default => \"\",\n \t\t     valid_re => qr/\\@.*\\./, confirm_only => 1);\n \tpush @initial_to, parse_address_line($to) if defined $to; # sanitized/validated later\n \t$prompting++;\n+} elsif ($email_protocol eq 'nntp' &&\n+\t !@initial_newsgroups &&\n+\t !defined $newsgroups_cmd) {\n+\tmy $newsgroup = ask(\"Which newsgroups should the message be sent to (if any)? \",\n+\t\t     default => \"\",\n+\t\t     valid_re => qr/[\\x20-\\x7f]+/, confirm_only => 1);\n+\tpush @initial_newsgroups, $newsgroup if defined $newsgroup; # sanitized/validated later\n+\t$prompting++;\n }\n\n\nNaturally, a function like this will become a method of the\ninstance without if/else cascade:\n\n+sub email_host_string {\n+\tif ($email_protocol eq 'nntp') {\n+\t\tif (defined $nntp_server_port) {\n+\t\t\treturn \"$nntp_server:$nntp_server_port\";\n+\t\t} else {\n+\t\t\treturn $nntp_server;\n+\t\t}\n+\n \t} else {\n-\t\treturn $smtp_server;\n+\t\tif (defined $smtp_server_port) {\n+\t\t\treturn \"$smtp_server:$smtp_server_port\";\n+\t\t} else {\n+\t\t\treturn $smtp_server;\n+\t\t}\n \t}\n }\n"},{"id":"215395","messageId":"7v38ufa6wb.fsf@alter.siamese.dyndns.org","threadId":"33579","inReplyTo":"87zjwofken.fsf@linux-k42r.v.cablecom.net","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-24T22:41:24Z","receivedAt":"2013-04-24T22:41:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@inf.ethz.ch> writes:\n\n> Łukasz Stelmach <l.stelmach@samsung.com> writes:\n>\n>> Enable sending patches to NNTP servers (Usenet, Gmane).\n>\n> I'm surprised Junio didn't mention this: your patch lacks the\n> Signed-off-by.\n\nHeh, that was because I took the patch as an early preview and not a\nfinal submission.  It came without documentation updates, and also\nit seemed to break t9001 for whatever reason.\n"},{"id":"215408","messageId":"87sj2fhzdx.fsf@samsung.com","threadId":"33579","inReplyTo":"7vip3bgax9.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Łukasz Stelmach","fromEmail":"l.stelmach@samsung.com","sentAt":"2013-04-25T06:56:26Z","receivedAt":"2013-04-25T06:56:26Z","isPatch":true,"sender":{"key":"l.stelmach@samsung.com","avatar":"https://gravatar.com/avatar/b5f9262ad19b1b6f1e74b8eba816455e059742e8d980fdefa9321976071642fc?d=mp&s=160"},"body":"It was <2013-04-24 śro 18:17>, when Junio C Hamano wrote:\n> l.stelmach@samsung.com (Łukasz Stelmach) writes:\n>\n>> It was <2013-04-23 wto 17:02>, when Junio C Hamano wrote:\n>>> Łukasz Stelmach <l.stelmach@samsung.com> writes:\n>>>\n>>>> Enable sending patches to NNTP servers (Usenet, Gmane).\n>>>> ---\n>>>>\n>>>> The patch implements support for sending messages to groups on NNTP\n>>>> serviers.\n>>>\n>>> Cute.\n>>>\n>>> A Perl guru might want to encapsulate the differences between $smtp\n>>> and $nntp codepaths into two Perl modules, but it looks like a good\n>>> starting point.\n>>\n>> You mean *one* perl module like Git::EmailTransport which hides the\n>> differences.\n>\n> What I meant was one class to handle SMTP and another for NNTP.\n>\n> You look at the --protocol option, choose one of these classes, and\n> initialize an instance of the chosen class.\n>\n> You can ask the chosen class to instantiate an instance without\n> if/else cascade like this:\n>\n> +\n> +# Transport specific setup\n> +my ($email_authuser, $email_authpass);\n> +if ($email_protocol eq 'nntp') {\n> +    $email_authuser = $nntp_authuser;\n> +    $email_authuser = $nntp_authuser;\n> +    @initial_to = @initial_cc = @bcclist = ();\n> +    $to_cmd = $cc_cmd = undef;\n> +    $no_cc = $no_bcc = 1;\n> +} else {\n> +    $email_authuser = $smtp_authuser;\n> +    $email_authpass = $smtp_authpass;\n> +    $newsgroups_cmd = undef;\n> +}\n> +\n\n[...]\n\nOK, I see. Good point. Where would you recommend me to put these modules\nand how to name them? I mean I don't want to make to much mess here (;\n\n-- \nŁukasz Stelmach\nSoftware wizzard\nSamsung Poland R&D Center\n"},{"id":"215409","messageId":"87li87hz4f.fsf@samsung.com","threadId":"33579","inReplyTo":"7v38ufa6wb.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Łukasz Stelmach","fromEmail":"l.stelmach@samsung.com","sentAt":"2013-04-25T07:02:08Z","receivedAt":"2013-04-25T07:02:08Z","isPatch":true,"sender":{"key":"l.stelmach@samsung.com","avatar":"https://gravatar.com/avatar/b5f9262ad19b1b6f1e74b8eba816455e059742e8d980fdefa9321976071642fc?d=mp&s=160"},"body":"It was <2013-04-25 czw 00:41>, when Junio C Hamano wrote:\n> Thomas Rast <trast@inf.ethz.ch> writes:\n>\n>> Łukasz Stelmach <l.stelmach@samsung.com> writes:\n>>\n>>> Enable sending patches to NNTP servers (Usenet, Gmane).\n>>\n>> I'm surprised Junio didn't mention this: your patch lacks the\n>> Signed-off-by.\n>\n> Heh, that was because I took the patch as an early preview and not a\n> final submission.  It came without documentation updates, and also\n> it seemed to break t9001 for whatever reason.\n\nI suppose that means I should write tests too. OK.\n\n-- \nŁukasz Stelmach\nSoftware wizzard\nSamsung Poland R&D Center\n"},{"id":"215455","messageId":"7vppxi4kkv.fsf@alter.siamese.dyndns.org","threadId":"33579","inReplyTo":"87sj2fhzdx.fsf@samsung.com","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-25T16:54:40Z","receivedAt":"2013-04-25T16:54:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"l.stelmach@samsung.com (Łukasz Stelmach) writes:\n\n> OK, I see. Good point. Where would you recommend me to put these modules\n> and how to name them? I mean I don't want to make to much mess here (;\n\nI would not recommend you to do any of the above now.  As I said, the\nopen-coded if/elsif cascade version you posted is fine as a starting\npoint.  I'd prefer to see it made work correctly as advertised first\nwith documentation updates and tests.\n\nA Perl guru might want to come and refactor the result once the code\nsolidifies, but that should be left as a separate series.\n"},{"id":"215459","messageId":"7vbo924ipd.fsf@alter.siamese.dyndns.org","threadId":"33579","inReplyTo":"7vppxi4kkv.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] send-email: support NNTP","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-25T17:35:10Z","receivedAt":"2013-04-25T17:35:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> l.stelmach@samsung.com (Łukasz Stelmach) writes:\n>\n>> OK, I see. Good point. Where would you recommend me to put these modules\n>> and how to name them? I mean I don't want to make to much mess here (;\n>\n> I would not recommend you to do any of the above now.  As I said, the\n> open-coded if/elsif cascade version you posted is fine as a starting\n> point.  I'd prefer to see it made work correctly as advertised first\n> with documentation updates and tests.\n>\n> A Perl guru might want to come and refactor the result once the code\n> solidifies, but that should be left as a separate series.\n\nAn alternative structure of the patch, if you are feeling brave,\ncould go like this:\n\n (1) With a thought process similar to what I illustrated in my\n     message you responded with \"OK, I see. Good point.\", identify\n     all the codepaths that will need to become methods that are\n     specific to the transport (SMTP or NNTP).\n\n (2) Without adding any NNTP goodies, refactor the current code to\n     use a single class for driving conversation with a SMTP server.\n     You will implement all the methods you identified in the\n     previous step and the result will become \"[PATCH 1/2]\n     send-email: refactor to use a transport-specific class\".\n\n (3) Implement a new class to drive conversation with an NNTP\n     server, that has the same set of methods as the SMTP one you\n     wrote in the previous step.  The result will become \"[PATCH\n     2/2] send-email: introduce NNTP transport\".  This would need\n     updates to the documentation.\n\nI do not necessarily suggest you to go this route, by the way. It is\nup to you and depends on how proficient you are (and how comfortable\nyou feel) dealing with modular Perl programs.\n"}]}