Re: [PATCH] send-email: support NNTP

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Łukasz Stelmach <l.stelmach@xxxxxxxxxxx> writes:

> Enable sending patches to NNTP servers (Usenet, Gmane).
> ---
>
> The patch implements support for sending messages to groups on NNTP serviers.

Cute.

A Perl guru might want to encapsulate the differences between $smtp
and $nntp codepaths into two Perl modules, but it looks like a good
starting point.

> The patch does not (attempts not to) change the default behavior i.e. to use sendmail
> and/or Net::SMTP. To use NNTP one needs to configure the server (see the help message)
> and protocol ("--protocol nntp"). Then after giving --newsgroups the
> message will be sent via NNTP. Like this one:
>
> perl git-send-email.perl --protocol nntp --newsgroups gmane.comp.version-control.git --nntp-server news.gmane.org 0001-send-email-support-NNTP.patch
>
>  git-send-email.perl |  156 +++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 125 insertions(+), 31 deletions(-)
>
> diff --git a/git-send-email.perl b/git-send-email.perl
> index bd13cc8..0356635 100755
> --- a/git-send-email.perl
> +++ b/git-send-email.perl
> @@ -54,12 +54,14 @@ git send-email [options] <file | directory | rev-list options >
>      --[no-]bcc              <str>  * Email Bcc:
>      --subject               <str>  * Email "Subject:"
>      --in-reply-to           <str>  * Email "In-Reply-To:"
> +    --newsgroups            <str>  * NNTP Newsgroups:
>      --[no-]annotate                * Review each patch that will be sent in an editor.
>      --compose                      * Open an editor for introduction.
>      --compose-encoding      <str>  * Encoding to assume for introduction.
>      --8bit-encoding         <str>  * Encoding to assume 8bit mails if undeclared
>  
>    Sending:
> +    --protocol              <str>  * 'smtp' or 'nntp'. Default 'smtp'.
>      --envelope-sender       <str>  * Email envelope sender.
>      --smtp-server       <str:int>  * Outgoing SMTP server to use. The port
>                                       is optional. Default 'localhost'.
> @@ -71,6 +73,12 @@ git send-email [options] <file | directory | rev-list options >
>      --smtp-ssl                     * Deprecated. Use '--smtp-encryption ssl'.
>      --smtp-domain           <str>  * The domain name sent to HELO/EHLO handshake
>      --smtp-debug            <0|1>  * Disable, enable Net::SMTP debug.
> +    --nntp-server       <str:int>  * Outgoing NNTP server to use. The port
> +                                     is optional.
> +    --nntp-server-port      <int>  * Outgoing NNTP server port.
> +    --nntp-user             <str>  * Username for NNTP AUTHINFO.
> +    --nntp-pass             <str>  * Password for NNTP AUTHINFO.
> +    --nntp-debug            <0|1>  * Disable, enable Net::NNTP debug.
>  
>    Automating:
>      --identity              <str>  * Use the sendemail.<id> options.
> @@ -138,12 +146,14 @@ sub format_2822_time {
>  my $have_email_valid = eval { require Email::Valid; 1 };
>  my $have_mail_address = eval { require Mail::Address; 1 };
>  my $smtp;
> +my $nntp;
>  my $auth;
>  
>  # Variables we fill in automatically, or via prompting:
>  my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
>  	$initial_reply_to,$initial_subject,@files,
> -	$author,$sender,$smtp_authpass,$annotate,$compose,$time);
> +	$author,$sender,$smtp_authpass,$annotate,$compose,$time,
> +	@initial_newsgroups, @newsgroups);
>  
>  my $envelope_sender;
>  
> @@ -192,7 +202,9 @@ sub do_edit {
>  
>  # Variables with corresponding config settings
>  my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc);
> -my ($to_cmd, $cc_cmd);
> +my ($to_cmd, $cc_cmd, $newsgroups_cmd);
> +my ($email_protocol) = 'smtp';
> +my ($nntp_server, $nntp_server_port, $nntp_authuser, $nntp_authpass);
>  my ($smtp_server, $smtp_server_port, @smtp_server_options);
>  my ($smtp_authuser, $smtp_encryption);
>  my ($identity, $aliasfiletype, @alias_files, $smtp_domain);
> @@ -202,6 +214,7 @@ my ($auto_8bit_encoding);
>  my ($compose_encoding);
>  
>  my ($debug_net_smtp) = 0;		# Net::SMTP, see send_message()
> +my ($debug_net_nntp) = 0;		# Net::NNTP, see send_message()
>  
>  my $not_set_by_user = "true but not set by the user";
>  
> @@ -235,6 +248,13 @@ my %config_settings = (
>      "from" => \$sender,
>      "assume8bitencoding" => \$auto_8bit_encoding,
>      "composeencoding" => \$compose_encoding,
> +    "nntpserver" => \$nntp_server,
> +    "nntpserverport" => \$nntp_server_port,
> +    "nntpuser" => \$nntp_authuser,
> +    "nntppass" => \$nntp_authpass,
> +    "protocol" => \$email_protocol,
> +    "newsgroups" => \@initial_newsgroups,
> +    "newsgroupscmd" => \$newsgroups_cmd,
>  );
>  
>  my %config_path_settings = (
> @@ -291,6 +311,7 @@ my $rc = GetOptions("h" => \$help,
>  		    "to-cmd=s" => \$to_cmd,
>  		    "no-to" => \$no_to,
>  		    "cc=s" => \@initial_cc,
> +		    "cc-cmd=s" => \$cc_cmd,
>  		    "no-cc" => \$no_cc,
>  		    "bcc=s" => \@bcclist,
>  		    "no-bcc" => \$no_bcc,
> @@ -304,11 +325,18 @@ my $rc = GetOptions("h" => \$help,
>  		    "smtp-encryption=s" => \$smtp_encryption,
>  		    "smtp-debug:i" => \$debug_net_smtp,
>  		    "smtp-domain:s" => \$smtp_domain,
> +		    "newsgroups=s" => \@initial_newsgroups,
> +		    "newsgroups-cmd" => \$newsgroups_cmd,
> +		    "nntp-server=s" => \$nntp_server,
> +		    "nntp-server-port=s" => \$nntp_server_port,
> +		    "nntp-user=s" => \$nntp_authuser,
> +		    "nntp-pass:s" => \$nntp_authpass,
> +		    "nntp-debug:i" => \$debug_net_nntp,
> +		    "protocol=s" => \$email_protocol,
>  		    "identity=s" => \$identity,
>  		    "annotate!" => \$annotate,
>  		    "compose" => \$compose,
>  		    "quiet" => \$quiet,
> -		    "cc-cmd=s" => \$cc_cmd,
>  		    "suppress-from!" => \$suppress_from,
>  		    "suppress-cc=s" => \@suppress_cc,
>  		    "signed-off-cc|signed-off-by-cc!" => \$signed_off_by_cc,
> @@ -390,6 +418,24 @@ foreach my $setting (values %config_bool_settings) {
>  	${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]}));
>  }
>  
> +unless ($email_protocol eq 'smtp' || $email_protocol eq 'nntp') {
> +	die "Unsupported protocol: $email_protocol";
> +}
> +
> +# Transport specific setup
> +my ($email_authuser, $email_authpass);
> +if ($email_protocol eq 'nntp') {
> +    $email_authuser = $nntp_authuser;
> +    $email_authuser = $nntp_authuser;
> +    @initial_to = @initial_cc = @bcclist = ();
> +    $to_cmd = $cc_cmd = undef;
> +    $no_cc = $no_bcc = 1;
> +} else {
> +    $email_authuser = $smtp_authuser;
> +    $email_authpass = $smtp_authpass;
> +    $newsgroups_cmd = undef;
> +}
> +
>  # 'default' encryption is none -- this only prevents a warning
>  $smtp_encryption = '' unless (defined $smtp_encryption);
>  
> @@ -668,8 +714,8 @@ EOT
>  		} elsif (/^From:\s*(.+)\s*$/i) {
>  			$sender = $1;
>  			next;
> -		} elsif (/^(?:To|Cc|Bcc):/i) {
> -			print "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n";
> +		} elsif (/^(?:To|Cc|Bcc|Newsgroup):/i) {
> +			print "To/Cc/Bcc/Newsgroup fields are not interpreted yet, they have been ignored\n";
>  			next;
>  		}
>  		print $c2 $_;
> @@ -761,12 +807,21 @@ if (!defined $sender) {
>  }
>  
>  my $prompting = 0;
> -if (!@initial_to && !defined $to_cmd) {
> +
> +if ($email_protocol eq 'smtp' && !@initial_to && !defined $to_cmd) {
>  	my $to = ask("Who should the emails be sent to (if any)? ",
>  		     default => "",
>  		     valid_re => qr/\@.*\./, confirm_only => 1);
>  	push @initial_to, parse_address_line($to) if defined $to; # sanitized/validated later
>  	$prompting++;
> +} elsif ($email_protocol eq 'nntp' &&
> +	 !@initial_newsgroups &&
> +	 !defined $newsgroups_cmd) {
> +	my $newsgroup = ask("Which newsgroups should the message be sent to (if any)? ",
> +		     default => "",
> +		     valid_re => qr/[\x20-\x7f]+/, confirm_only => 1);
> +	push @initial_newsgroups, $newsgroup if defined $newsgroup; # sanitized/validated later
> +	$prompting++;
>  }
>  
>  sub expand_aliases {
> @@ -802,7 +857,7 @@ if (defined $initial_reply_to) {
>  	$initial_reply_to = "<$initial_reply_to>" if $initial_reply_to ne '';
>  }
>  
> -if (!defined $smtp_server) {
> +if ($email_protocol eq 'smtp' && !defined $smtp_server) {
>  	foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {
>  		if (-x $_) {
>  			$smtp_server = $_;
> @@ -1048,41 +1103,56 @@ sub maildomain {
>  	return maildomain_net() || maildomain_mta() || 'localhost.localdomain';
>  }
>  
> -sub smtp_host_string {
> -	if (defined $smtp_server_port) {
> -		return "$smtp_server:$smtp_server_port";
> +sub email_host_string {
> +	if ($email_protocol eq 'nntp') {
> +		if (defined $nntp_server_port) {
> +			return "$nntp_server:$nntp_server_port";
> +		} else {
> +			return $nntp_server;
> +		}
> +
>  	} else {
> -		return $smtp_server;
> +		if (defined $smtp_server_port) {
> +			return "$smtp_server:$smtp_server_port";
> +		} else {
> +			return $smtp_server;
> +		}
>  	}
>  }
>  
>  # Returns 1 if authentication succeeded or was not necessary
>  # (smtp_user was not specified), and 0 otherwise.
>  
> -sub smtp_auth_maybe {
> -	if (!defined $smtp_authuser || $auth) {
> +sub email_auth_maybe {
> +	if (!defined $email_authuser || $auth) {
>  		return 1;
>  	}
>  
>  	# Workaround AUTH PLAIN/LOGIN interaction defect
>  	# with Authen::SASL::Cyrus
> -	eval {
> -		require Authen::SASL;
> -		Authen::SASL->import(qw(Perl));
> -	};
> +	if ($email_protocol eq 'smtp') {
> +		eval {
> +			require Authen::SASL;
> +			Authen::SASL->import(qw(Perl));
> +		};
> +	}
>  
>  	# TODO: Authentication may fail not because credentials were
>  	# invalid but due to other reasons, in which we should not
>  	# reject credentials.
>  	$auth = Git::credential({
> -		'protocol' => 'smtp',
> -		'host' => smtp_host_string(),
> -		'username' => $smtp_authuser,
> +		'protocol' => $email_protocol,
> +		'host' => email_host_string(),
> +		'username' => $email_authuser,
>  		# if there's no password, "git credential fill" will
>  		# give us one, otherwise it'll just pass this one.
> -		'password' => $smtp_authpass
> +		'password' => $email_authpass
>  	}, sub {
>  		my $cred = shift;
> +		if ($email_protocol eq 'nntp') {
> +			return !!$nntp->authinfo($cred->{'username'},
> +						 $cred->{'password'});
> +		}
>  		return !!$smtp->auth($cred->{'username'}, $cred->{'password'});
>  	});
>  
> @@ -1099,7 +1169,7 @@ sub send_message {
>  		      not grep { $cc eq $_ || $_ =~ /<\Q${cc}\E>$/ } @recipients
>  		    }
>  	       @cc);
> -	my $to = join (",\n\t", @recipients);
> +	my $to = join (",\n\t", (($email_protocol eq 'nntp') ? @newsgroups : @recipients));
>  	@recipients = unique_email_list(@recipients,@cc,@bcclist);
>  	@recipients = (map { extract_valid_address_or_die($_) } @recipients);
>  	my $date = format_2822_time($time++);
> @@ -1117,12 +1187,17 @@ sub send_message {
>  	make_message_id() unless defined($message_id);
>  
>  	my $header = "From: $sanitized_sender
> -To: $to${ccline}
>  Subject: $subject
>  Date: $date
>  Message-Id: $message_id
>  X-Mailer: git-send-email $gitversion
>  ";
> +	if ($email_protocol eq 'nntp') {
> +		$header = "Newsgroups: $to\n" . $header;
> +	} else {
> +		$header = "To: $to${ccline}\n" . $header;
> +	}
> +
>  	if ($reply_to) {
>  
>  		$header .= "In-Reply-To: $reply_to\n";
> @@ -1174,6 +1249,18 @@ X-Mailer: git-send-email $gitversion
>  
>  	if ($dry_run) {
>  		# We don't want to send the email.
> +	} elsif ($email_protocol eq 'nntp') {
> +		if (!defined $nntp_server) {
> +			die "The requires NNTP server is not properly defined."
> +		}
> +		require Net::NNTP;
> +		$nntp =  Net::NNTP->new(email_host_string(),
> +		                        Debug => $debug_net_nntp);
> +		email_auth_maybe or die $nntp->message;
> +		$nntp->post or die $nntp->message;
> +		$nntp->datasend("$header\n$message") or die $nntp->message;
> +		$nntp->dataend() or die $nntp->message;
> +		$nntp->code eq "240" or die "Failed to send $subject\n".$nntp->message;
>  	} elsif ($smtp_server =~ m#^/#) {
>  		my $pid = open my $sm, '|-';
>  		defined $pid or die $!;
> @@ -1195,11 +1282,10 @@ X-Mailer: git-send-email $gitversion
>  			$smtp ||= Net::SMTP::SSL->new($smtp_server,
>  						      Hello => $smtp_domain,
>  						      Port => $smtp_server_port);
> -		}
> -		else {
> +		} else {
>  			require Net::SMTP;
>  			$smtp_domain ||= maildomain();
> -			$smtp ||= Net::SMTP->new(smtp_host_string(),
> +			$smtp ||= Net::SMTP->new(email_host_string(),
>  						 Hello => $smtp_domain,
>  						 Debug => $debug_net_smtp);
>  			if ($smtp_encryption eq 'tls' && $smtp) {
> @@ -1227,7 +1313,7 @@ X-Mailer: git-send-email $gitversion
>  			    defined $smtp_server_port ? " port=$smtp_server_port" : "";
>  		}
>  
> -		smtp_auth_maybe or die $smtp->message;
> +		email_auth_maybe or die $smtp->message;
>  
>  		$smtp->mail( $raw_from ) or die $smtp->message;
>  		$smtp->to( @recipients ) or die $smtp->message;
> @@ -1240,7 +1326,9 @@ X-Mailer: git-send-email $gitversion
>  		printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
>  	} else {
>  		print (($dry_run ? "Dry-" : "")."OK. Log says:\n");
> -		if ($smtp_server !~ m#^/#) {
> +		if ($email_protocol eq 'nntp') {
> +			print "Server: $nntp_server\n";
> +		} elsif ($smtp_server !~ m#^/#) {
>  			print "Server: $smtp_server\n";
>  			print "MAIL FROM:<$raw_from>\n";
>  			foreach my $entry (@recipients) {
> @@ -1250,9 +1338,10 @@ X-Mailer: git-send-email $gitversion
>  			print "Sendmail: $smtp_server ".join(' ',@sendmail_parameters)."\n";
>  		}
>  		print $header, "\n";
> -		if ($smtp) {
> -			print "Result: ", $smtp->code, ' ',
> -				($smtp->message =~ /\n([^\n]+\n)$/s), "\n";
> +		my $transport = $nntp || $smtp;
> +		if ($transport) {
> +			print "Result: ", $transport->code, ' ',
> +				($transport->message =~ /\n([^\n]+\n)$/s), "\n";
>  		} else {
>  			print "Result: OK\n";
>  		}
> @@ -1383,6 +1472,9 @@ foreach my $t (@files) {
>  	}
>  	close $fh;
>  
> +	push @newsgroups, recipients_cmd("newsgroups-cmd", "newsgroups",
> +					 $newsgroups_cmd, $t)
> +		if defined $newsgroups_cmd;
>  	push @to, recipients_cmd("to-cmd", "to", $to_cmd, $t)
>  		if defined $to_cmd;
>  	push @cc, recipients_cmd("cc-cmd", "cc", $cc_cmd, $t)
> @@ -1430,6 +1522,7 @@ foreach my $t (@files) {
>  	@to = validate_address_list(sanitize_address_list(@to));
>  	@cc = validate_address_list(sanitize_address_list(@cc));
>  
> +	@newsgroups = (@initial_newsgroups, @newsgroups);
>  	@to = (@initial_to, @to);
>  	@cc = (@initial_cc, @cc);
>  
> @@ -1479,6 +1572,7 @@ sub cleanup_compose_files {
>  }
>  
>  $smtp->quit if $smtp;
> +$nntp->quit if $nntp;
>  
>  sub unique_email_list {
>  	my %seen;
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]