(Relay) Handle unexpected replies and disconnections adequately
[mgsmtp.git] / Spool.pas
index 558205d87ff701ee04cdd100eebf566552bbc442..1e4510192f8dd04f97fbf947dd26e0835523d652 100644 (file)
--- a/Spool.pas
+++ b/Spool.pas
@@ -1,6 +1,6 @@
 {
    MegaBrutal's SMTP Server (MgSMTP)
-   Copyright (C) 2010-2014 MegaBrutal
+   Copyright (C) 2010-2015 MegaBrutal
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
@@ -133,7 +133,7 @@ type
       SpoolConfig: TSpoolConfig;
       SpoolFilters: TSpoolFilters;
       function DeliverLocalMessage(SpoolObject: TSpoolObjectReader; MailboxPtr: pointer; ReturnPath, Recipient: string): integer;
-      procedure DeliverRelayMessage(SpoolObject: TSpoolObjectReader; Relayer: TRelayer);
+      function DeliverRelayMessage(SpoolObject: TSpoolObjectReader; Relayer: TRelayer): boolean;
       procedure HandleFailure(SpoolObject: TSpoolObjectReader; IsLocal: boolean; FailEnvelope: TEnvelope; FailedRecipient: TRecipient; AddStatus: integer; FailMsg: string);
       procedure HandleDeliveryResults(SpoolObject: TSpoolObjectReader; IsLocal: boolean; Envelope, FailEnvelope: TEnvelope; AddStatus: integer; FailMsg: string);
       procedure CreateBounceMessage(SourceSpoolObject: TSpoolObjectReader; FailEnvelope: TEnvelope);
@@ -662,11 +662,8 @@ begin
             R:= Mailbox^.DeliverMessagePart(LockID, Chunk);
          end;
          if R then begin
-            if Mailbox^.FinishDeliverMessage(LockID) then begin
-               Result:= 0;
-               { It's better to set in Execute. }
-               {SpoolObject.QuickSetDeliveryStatus(Recipient, DS_DELIVERED);}
-            end
+            if Mailbox^.FinishDeliverMessage(LockID) then
+               Result:= 0
             else
                Result:= 4;
          end
@@ -682,7 +679,10 @@ begin
       Result:= 1;
 end;
 
-procedure TDeliveryThread.DeliverRelayMessage(SpoolObject: TSpoolObjectReader; Relayer: TRelayer);
+function TDeliveryThread.DeliverRelayMessage(SpoolObject: TSpoolObjectReader; Relayer: TRelayer): boolean;
+{ Relay message to remote server.
+  Returns true if the transaction went through (doesn't necessarily mean
+  that the message was actually accepted). }
 var Headers, Chunk: TStrings; R: boolean;
 begin
    if Relayer.PrepareSendMessage then begin
@@ -690,11 +690,12 @@ begin
       Chunk:= TStringList.Create;
       { Leave a line between the headers and the body. }
       Headers.Add('');
+
       R:= Relayer.DeliverMessagePart(Headers);
       while (not SpoolObject.IsEOF) and R do begin
-         { Maybe constant "32" should be configurable? }
+         { Maybe constant "64" should be configurable? }
          Chunk.Clear;
-         SpoolObject.ReadChunk(Chunk, 32);
+         SpoolObject.ReadChunk(Chunk, 64);
          R:= Relayer.DeliverMessagePart(Chunk);
       end;
       if R then begin
@@ -702,9 +703,12 @@ begin
       end
       else
          SpoolObject.SetDeliveryStatus(false, Relayer.Envelope, DS_DELAYED or DS_CONNECTIONFAIL);
+
+      Result:= R;
       Chunk.Free;
       Headers.Free;
-   end;
+   end
+   else Result:= false;
 end;
 
 function TDeliveryThread.NeedSendReport(SpoolObject: TSpoolObject): boolean;
@@ -866,9 +870,10 @@ begin
                         if Relayer.Greet then
                            if Relayer.SendEnvelope then
                               DeliverRelayMessage(SpoolObject, Relayer);
+
+                        AssignDeliveryStatusToSMTPCodes(CurrEnv, Relayer.IsTransactionComplete);
                         Relayer.CloseConnection;
                         Relayer.Free;
-                        AssignDeliveryStatusToSMTPCodes(CurrEnv);
                         HandleDeliveryResults(SpoolObject, false, CurrEnv, FailEnv, 0, '');
                      end
                      else begin