summaryrefslogtreecommitdiff
path: root/git-send-email.perl
diff options
context:
space:
mode:
Diffstat (limited to 'git-send-email.perl')
-rwxr-xr-xgit-send-email.perl67
1 files changed, 52 insertions, 15 deletions
diff --git a/git-send-email.perl b/git-send-email.perl
index 798d59b84f..1f613fa979 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1419,7 +1419,7 @@ sub smtp_auth_maybe {
die "invalid smtp auth: '${smtp_auth}'";
}
- # TODO: Authentication may fail not because credentials were
+ # Authentication may fail not because credentials were
# invalid but due to other reasons, in which we should not
# reject credentials.
$auth = Git::credential({
@@ -1431,24 +1431,61 @@ sub smtp_auth_maybe {
'password' => $smtp_authpass
}, sub {
my $cred = shift;
+ my $result;
+ my $error;
+
+ # catch all SMTP auth error in a unified eval block
+ eval {
+ if ($smtp_auth) {
+ my $sasl = Authen::SASL->new(
+ mechanism => $smtp_auth,
+ callback => {
+ user => $cred->{'username'},
+ pass => $cred->{'password'},
+ authname => $cred->{'username'},
+ }
+ );
+ $result = $smtp->auth($sasl);
+ } else {
+ $result = $smtp->auth($cred->{'username'}, $cred->{'password'});
+ }
+ 1; # ensure true value is returned if no exception is thrown
+ } or do {
+ $error = $@ || 'Unknown error';
+ };
+
+ return ($error
+ ? handle_smtp_error($error)
+ : ($result ? 1 : 0));
+ });
- if ($smtp_auth) {
- my $sasl = Authen::SASL->new(
- mechanism => $smtp_auth,
- callback => {
- user => $cred->{'username'},
- pass => $cred->{'password'},
- authname => $cred->{'username'},
- }
- );
+ return $auth;
+}
- return !!$smtp->auth($sasl);
+sub handle_smtp_error {
+ my ($error) = @_;
+
+ # Parse SMTP status code from error message in:
+ # https://www.rfc-editor.org/rfc/rfc5321.html
+ if ($error =~ /\b(\d{3})\b/) {
+ my $status_code = $1;
+ if ($status_code =~ /^4/) {
+ # 4yz: Transient Negative Completion reply
+ warn "SMTP transient error (status code $status_code): $error";
+ return 1;
+ } elsif ($status_code =~ /^5/) {
+ # 5yz: Permanent Negative Completion reply
+ warn "SMTP permanent error (status code $status_code): $error";
+ return 0;
}
+ # If no recognized status code is found, treat as transient error
+ warn "SMTP unknown error: $error. Treating as transient failure.";
+ return 1;
+ }
- return !!$smtp->auth($cred->{'username'}, $cred->{'password'});
- });
-
- return $auth;
+ # If no status code is found, treat as transient error
+ warn "SMTP generic error: $error";
+ return 1;
}
sub ssl_verify_params {