Skip to content

Instantly share code, notes, and snippets.

@xdg
Created December 26, 2015 03:42
Show Gist options
  • Save xdg/45d3590bf90e57bcbfbe to your computer and use it in GitHub Desktop.
Save xdg/45d3590bf90e57bcbfbe to your computer and use it in GitHub Desktop.
commit 7c8140ad08d6022d1f33feb091513356b032db5c (HEAD -> chunking)
Author: David Golden <xdg@xdg.me>
Date: Fri Dec 25 12:16:18 2015 -0500
Send body with BDAT if chunking supported
diff --git a/lib/Email/Sender/Transport/SMTP.pm b/lib/Email/Sender/Transport/SMTP.pm
index 6de9234..83b4e0e 100644
--- a/lib/Email/Sender/Transport/SMTP.pm
+++ b/lib/Email/Sender/Transport/SMTP.pm
@@ -209,29 +209,10 @@ sub send_email {
# restore Pobox's support for streaming, code-based messages, and arrays here
# -- rjbs, 2008-12-04
+ my $send_method = exists ${*$smtp}{'net_smtp_esmtp'}{CHUNKING}
+ ? '_send_bdat' : '_send_data';
- $smtp->data or $FAULT->("error at DATA start");
-
- my $msg_string = $email->as_string;
- my $hunk_size = $self->_hunk_size;
-
- while (length $msg_string) {
- my $next_hunk = substr $msg_string, 0, $hunk_size, '';
-
- # For the need to downgrade, see
- # https://rt.cpan.org/Ticket/Display.html?id=104433
- #
- # The ||0 is there because when we've mocked Net::SMTP, there is no
- # version. We can't get the ->VERSION call to hit the mock, because we get
- # the mock from ->new. We don't want to create a new SMTP just to get the
- # version, and we can't rely on $smtp being a Net::SMTP object.
- # -- rjbs, 2015-08-10
- utf8::downgrade($next_hunk) if (Net::SMTP->VERSION || 0) < 3.07;
-
- $smtp->datasend($next_hunk) or $FAULT->("error at during DATA");
- }
-
- $smtp->dataend or $FAULT->("error at after DATA");
+ $self->$send_method($email, $smtp, $FAULT);
my $message = $smtp->message;
@@ -250,6 +231,62 @@ sub send_email {
sub _hunk_size { 2**20 } # send messages to DATA in hunks of 1 mebibyte
+sub _send_data {
+ my ($self, $email, $smtp, $FAULT) = @_;
+
+ $smtp->data or $FAULT->("error at DATA start");
+
+ my $msg_string = $email->as_string;
+ my $hunk_size = $self->_hunk_size;
+
+ while (length $msg_string) {
+ my $next_hunk = substr $msg_string, 0, $hunk_size, '';
+
+ # For the need to downgrade, see
+ # https://rt.cpan.org/Ticket/Display.html?id=104433
+ #
+ # The ||0 is there because when we've mocked Net::SMTP, there is no
+ # version. We can't get the ->VERSION call to hit the mock, because we get
+ # the mock from ->new. We don't want to create a new SMTP just to get the
+ # version, and we can't rely on $smtp being a Net::SMTP object.
+ # -- rjbs, 2015-08-10
+ utf8::downgrade($next_hunk) if (Net::SMTP->VERSION || 0) < 3.07;
+
+ $smtp->datasend($next_hunk) or $FAULT->("error at during DATA");
+ }
+
+ $smtp->dataend or $FAULT->("error at after DATA");
+}
+
+sub _send_bdat {
+ my ($self, $email, $smtp, $FAULT) = @_;
+
+ my $msg_string = $email->as_string;
+ my $hunk_size = $self->_hunk_size;
+
+ my $n=1;
+ while (length $msg_string) {
+ my $next_hunk = substr $msg_string, 0, $hunk_size, '';
+
+ # For the need to downgrade, see
+ # https://rt.cpan.org/Ticket/Display.html?id=104433
+ #
+ # The ||0 is there because when we've mocked Net::SMTP, there is no
+ # version. We can't get the ->VERSION call to hit the mock, because we get
+ # the mock from ->new. We don't want to create a new SMTP just to get the
+ # version, and we can't rely on $smtp being a Net::SMTP object.
+ # -- rjbs, 2015-08-10
+ utf8::downgrade($next_hunk) if (Net::SMTP->VERSION || 0) < 3.07;
+
+ $smtp->_BDAT(length $next_hunk, (length $msg_string == 0 ? ("LAST") : ""))
+ && $smtp->rawdatasend($next_hunk)
+ && $smtp->response() == $smtp->CMD_OK
+ or $FAULT->("error at BDAT hunk $n");
+
+ $n++;
+ }
+}
+
sub success {
my $self = shift;
my $success = Moo::Role->create_class_with_roles('Email::Sender::Success', 'Email::Sender::Role::HasMessage')->new(@_);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment