All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Witten <mfwitten@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH RFC 08/10] send-email: Add --sleep for email throttling
Date: Sat, 11 Apr 2009 14:08:26 -0500	[thread overview]
Message-ID: <1239476908-25944-8-git-send-email-mfwitten@gmail.com> (raw)
In-Reply-To: <1239476908-25944-7-git-send-email-mfwitten@gmail.com>

The --sleep option provides a means for specifying that there
should be a certain number of seconds of delay after sending
a certain number of emails; see Documentation/git-send-email.txt

Signed-off-by: Michael Witten <mfwitten@gmail.com>
---
 Documentation/git-send-email.txt |   30 +++++++++++++++
 git-send-email.perl              |   74 +++++++++++++++++++++++++++++++++++---
 2 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 12845d6..f0c2e7b 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -168,6 +168,36 @@ Automating
 	entire patch series. Default is the value of the 'sendemail.chainreplyto'
 	configuration value; if that is unspecified, default to --chain-reply-to.
 
+--sleep=<seconds>[,<burst>]::
+	This option specfies that send-email should sleep for <seconds>
+	after sending <burst> messages as quickly as possible; <seconds>
+	should be an integer >= 0 and <burst> should be an integer >= 1.
+	This mode of operation attacks 2 problems: email throttling and
+	arrival disorder. Default is the value of the 'sendemail.sleep'
+	configuration variable, or '0' if that does not exist.
++
+By default, send-email tries to send one patch per email as quickly as
+possible. Unfortunately, some email services restrict a user by refusing
+to send more than some maximum number of email messages, M, in a given
+period of seconds, S. This can be troublesome if the patch series has
+more than M patches, because the server will ultimately refuse to send
+some of them. In this case, simply pass '--sleep=S,M' or '--sleep S,M'
+or set sendemail.sleep to 'S,M'.
++
+Moreover, the emails often arrive at the final destination out of order;
+though send-email manipulates the date fields and usually chains subsequent
+emails via the In-Reply-To headers, some mail viewers nevertheless insist
+on presenting them by order of arrival. This may be mitigated by using
+something like '--sleep 60' (the equivalent of '--sleep 60,1'), so that
+there is a 60 second delay between sending each patch.
++
+*Note*: Because of varying routes and batching schemes, there is no delay
+that can guarantee the correct arrival order. Obviously, one solution is to
+choose an obscenely large number, so be prepared to run send-email in the
+background. Of course, spreading emails across time makes it more likely
+that unrelated email messages arrive between patches. Therefore, send-email
+warns you if both --sleep and --no-chain-reply-to are used.
+
 --identity=<id>::
 	A configuration identity. When given, causes values in the
 	'sendemail.<id>' subsection to take precedence over
diff --git a/git-send-email.perl b/git-send-email.perl
index 4f0462f..c26a1b5 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -77,6 +77,7 @@ git send-email [options] <file | directory | rev-list options >
     --smtp-ssl                     * Deprecated. Use '--smtp-encryption ssl'.
 
   Automating:
+    --sleep      <secs>[,<burst>]  * Delay <secs> every <burst> email(s).
     --identity               <id>  * Use the sendemail.<id> options.
     --cc-cmd            <command>  * Email Cc: via `<command> \$patch_path`
     --suppress-cc      <category>  * author, self, sob, cc, cccmd, body,
@@ -194,7 +195,7 @@ sub do_edit {
 }
 
 # Variables with corresponding config settings
-my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd);
+my ($sleep, $thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd);
 my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
 my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
 my ($validate, $confirm);
@@ -210,6 +211,7 @@ my %config_bool_settings = (
 );
 
 my %config_settings = (
+	"sleep" => \$sleep,
 	"smtpserver" => \$smtp_server,
 	"smtpserverport" => \$smtp_server_port,
 	"smtpuser" => \$smtp_authuser,
@@ -262,6 +264,7 @@ my $rc = GetOptions(
 	"cc=s" => \@initial_cc,
 	"bcc=s" => \@bcclist,
 	"chain-reply-to!" => \$chain_reply_to,
+	"sleep=s" => \$sleep,
 	"smtp-server=s" => \$smtp_server,
 	"smtp-server-port=i" => \$smtp_server_port,
 	"smtp-user=s" => \$smtp_authuser,
@@ -334,6 +337,43 @@ foreach my $setting (values %config_bool_settings) {
 	${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]}));
 }
 
+#### Parse input
+
+my ($sleep_seconds, $sleep_burst);
+
+if (defined $sleep) {{
+
+	unless ($chain_reply_to) {
+
+		print "Both --sleep and --no-chain-reply-to are in effect.\n";
+		print "Therefore, it is much more likely that unrelated\n";
+		print "email messages will appear between any 2 of your\n";
+		print "patches.\n\n";
+
+		$_ = ask(
+			"How to proceed? ([q]uit | --[s]leep | --no-[c]hain | [n]either | [b]oth): ",
+			valid_re => qr/^(?:b|s|c|n|q)/i,
+			default => 'b'
+		);
+
+		/^b/                                               or
+		/^s/ and $chain_reply_to = 1                       or
+		/^c/ and $sleep = undef, last                      or
+		/^n/ and $chain_reply_to = 1, $sleep = undef, last or
+		/^q/ and exit;
+	}
+
+	$sleep =~ /^(\d+)(?:,(\d+))?$/
+		or  print "Should be '--sleep=<seconds>[,<burst>]', but got '--sleep=\"$sleep\"'\n"
+		and exit;
+
+	# Explicitly convert to integers to avoid repeated conversion:
+	# (<burst> = 0 is not defined, but let's be nice and absorb it)
+
+	$sleep_seconds = 0+$1;
+	$sleep_burst   = $2 ? 0+$2 : 1;
+}}
+
 # 'default' encryption is none -- this only prevents a warning
 $smtp_encryption = '' unless (defined $smtp_encryption);
 
@@ -1041,8 +1081,12 @@ $references = $initial_reply_to || '';
 $subject = $initial_subject;
 $message_num = 0;
 
-foreach my $t (@files) {
-	open(F,"<",$t) or die "can't open file $t";
+my $burst_count = $sleep_burst;
+my $time_of_last_message;
+
+for (my $index = 0; $index < @files; $index++) {
+	my $file = $files[$index];
+	open(F,"<",$file) or die "can't open file $file";
 
 	my $author = undef;
 	my $author_encoding;
@@ -1151,7 +1195,7 @@ foreach my $t (@files) {
 	close F;
 
 	if (defined $cc_cmd && !$suppress_cc{'cccmd'}) {
-		open(F, "$cc_cmd $t |")
+		open(F, "$cc_cmd $file |")
 			or die "(cc-cmd) Could not execute '$cc_cmd'";
 		while(<F>) {
 			my $c = $_;
@@ -1198,7 +1242,27 @@ foreach my $t (@files) {
 
 	my $message_was_sent = send_message();
 
-	# set up for the next message
+	# Throttle the outgoing rate:
+
+	if ($sleep_seconds && $message_was_sent) {
+
+		$time_of_last_message = time;
+
+		unless (--$burst_count) {  # unless we can send more
+
+			$burst_count = $sleep_burst;
+
+			my $already_elapsed = time - $time_of_last_message;
+
+			if ($already_elapsed < $sleep_seconds && $index < $#files) {
+				my $this_long = $sleep_seconds - $already_elapsed;
+				while (($this_long -= sleep $this_long) > 0) {}
+			}
+		}
+	}
+
+	# set up for the next message:
+
 	if ($message_was_sent and $chain_reply_to || not defined $reply_to || length($reply_to) == 0) {
 		$reply_to = $message_id;
 		if (length $references > 0) {
-- 
1.6.2.2.479.g2aec

  reply	other threads:[~2009-04-11 19:17 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-11 19:08 [PATCH RFC 01/10] Docs: send-email: Put options back into alphabetical order Michael Witten
2009-04-11 19:08 ` [PATCH RFC 02/10] Docs: send-email: Remove superfluous information in CONFIGURATION Michael Witten
2009-04-11 19:08   ` [PATCH RFC 03/10] send-email: Cleanup the usage text and docs a bit Michael Witten
2009-04-11 19:08     ` [PATCH RFC 04/10] send-email: --smtp-server-port should take an integer Michael Witten
2009-04-11 19:08       ` [PATCH RFC 05/10] send-email: Handle "GIT:" rather than "GIT: " during --compose Michael Witten
2009-04-11 19:08         ` [PATCH RFC 06/10] send-email: References: should only reference what is actually sent Michael Witten
2009-04-11 19:08           ` [PATCH RFC 07/10] send-email: Remove horrible mix of tabs and spaces Michael Witten
2009-04-11 19:08             ` Michael Witten [this message]
2009-04-11 19:08               ` [PATCH RFC 09/10] send-email: Minor cleanup of $smtp_server usage and send_message() Michael Witten
2009-04-11 19:08                 ` [PATCH RFC 10/10] send-email: --compose takes optional argument to existing file Michael Witten
2009-04-11 19:25                   ` Sverre Rabbelier
2009-04-11 19:38                     ` Michael Witten
2009-04-11 21:58                 ` [PATCH RFC 09/10] send-email: Minor cleanup of $smtp_server usage and send_message() Stephen Boyd
2009-04-11 22:13                   ` Michael Witten
2009-04-12  2:27               ` [PATCH RFC 08/10] send-email: Add --sleep for email throttling Jay Soffian
2009-04-12  2:59               ` Michael Witten
2009-04-11 19:17             ` [PATCH RFC 07/10] send-email: Remove horrible mix of tabs and spaces Sverre Rabbelier
2009-04-11 19:31               ` Michael Witten
2009-04-13  1:49               ` Miles Bader
2009-04-13  2:15                 ` Michael Witten
2009-04-11 21:52           ` [PATCH RFC 06/10] send-email: References: should only reference what is actually sent Stephen Boyd
2009-04-11 22:42             ` Michael Witten
2009-04-11 21:42   ` [PATCH RFC 02/10] Docs: send-email: Remove superfluous information in CONFIGURATION Stephen Boyd

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1239476908-25944-8-git-send-email-mfwitten@gmail.com \
    --to=mfwitten@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.