0

A couple of years ago, I wrote a throw away program that was to be used once and deleted. My client uses it daily, ever since.

Its purpose is to pull down "ticket" mail and read an Ack + number from the body. There may be several and all are read into a Tstringlist to process.

Yesterday they switched from RackSpace to Amazon Work Mail. I have the authentication working but my program does not see the mail bodies. It gets the count correctly and I see the header under the debugger but it does not get copied to the Memo1, either.

I have verified the mail through Amazon's web interface and see the subject and bodies. They are all there.

The mail has been deleted and restored multiple times (if that could be the issue). That was never a problem with RackSpace.

RackSpace did not use encryption but Amazon does use TLS.

Here is what worked worked until Amazon --

Can anyone see why I am still able to see a mail count but no bodies?

The Main Process

procedure TForm1.GetGmailBodyTextParts;
var
  MsgIndex, i: integer;
  MsgObject: TIdMessage;
  TheUID: string;
  fatalError: boolean;
  s, sSerialNum, sAck: string;
  msgStatus: string;
  failed: boolean;
  ToDelete: integer;
  Confirmed: array of integer;
  iTotalMsgs: integer;
  ackedSuccess: integer;
  totalInList: integer;
  ackList: TStringList;
  timeStart, timeStop: TDateTime;
  elapsedTime: integer;
  mailPerTime: double;
const
  FILE_EXT = '.TXT';
begin
  ToDelete := 0;
  ackedSuccess := 0;
  fatalError := false;
  Memo1.Clear;
  Memo2.Clear;
  IMAPClient.Disconnect(true);
  IMAPClient.Connect;
  timeStart := GetTime;
  try
    ackList := TStringList.Create;
    ackList.Duplicates := dupIgnore;
    ackList.Sorted := true;
    if (IMAPClient.SelectMailBox(MailBoxName) = true) then
    begin
      iTotalMsgs := IMAPClient.MailBox.TotalMsgs;
      ProgressBar1.Max := iTotalMsgs;
      StatusBar1.Panels[5].Text := IntToStr(iTotalMsgs);
      for MsgIndex := 1 to IMAPClient.MailBox.TotalMsgs do
      begin

        MsgObject := TIdMessage.Create(nil);
        failed := false;
        ToDelete := 0;
        try

          If not(IMAPClient.Retrieve(MsgIndex, MsgObject)) then continue;
          MsgObject.Headers.ConvertToStdValues(Memo1.Lines);

          if mfDeleted in MsgObject.Flags then
          begin
            dec(iTotalMsgs);
            StatusBar1.Panels[5].Text := IntToStr(iTotalMsgs);

            FreeAndNil(MsgObject);
            continue; // flagged for delete
          end;

          StatusBar1.Panels[3].Text := IntToStr(MsgIndex);
          StatusBar1.Refresh;
          application.ProcessMessages;

          SetLength(Confirmed, Succ(ToDelete));
          Confirmed[ToDelete] := MsgIndex;
          Inc(ToDelete);

          if not MsgObject.IsBodyEmpty then
          begin
            ackList.Clear;
            ackList.AddStrings(RemoveDups(MsgObject.Body));

            Memo2.Lines.AddStrings(ackList);
            totalInList := ackList.Count;

            for i := 0 to totalInList - 1 do
            begin
              s := Trim(ackList[i]);
              sSerialNum := Trim(copy(s, 0, pos(#44, s) - 2));
              sAck := Trim(copy(s, pos(#44, s) + 2, maxChar));
              try
                ackedSuccess := 0;
                updRespLog.Parameters.ParamByName('ack').Value := sAck;
                updRespLog.Parameters.ParamByName('serialNo').Value :=
                  sSerialNum;
                ackedSuccess := updRespLog.ExecSQL;
                assert(ackedSuccess > 0, 'Cannot find ' + sSerialNum +
                  ' to Ack - missing ');
                if ackedSuccess > 0 then
                begin
                  delRespActWait.Parameters.ParamByName('serialNo').Value :=
                    sSerialNum;
                  delRespActWait.ExecSQL;
                end;
              except
                on e: exception do
                begin

                  LogResult.LogType := ltMissing;
                  LogResult.Status := 'Missing: ' + sSerialNum;
                  WriteLog(LogResult);
                  Memo2.Lines.add(LogResult.ExcepMsg);

                  ackedSuccess := 1;

                end;
              end; // except

            end; // for i := 0 to ListBox1.Count - 1 do
            LogResult.MethodName := 'Processing Mail, saving copy';
            LogResult.DataStream := 'serialNumbers: ' + ackList.CommaText;
            LogResult.LogType := ltInfo;
            WriteLog(LogResult);
            Memo2.Lines.add('Processed ' + sSerialNum + ' Ack');
            Memo2.Lines.add('Processed ' + IntToStr(i) + ' of ' +
              IntToStr(totalInList));
            MsgObject.Body.SaveToFile(bodyTextDir + '\' + callCenter +
              FormatDateTime('yyyy-mm-dd hh-mm-ss', MsgObject.Date) + FILE_EXT);

          end
          else
          begin

            LogResult.MethodName := 'Processing Mail';
            LogResult.Status := 'mail body empty-nothing to do!!';
            LogResult.DataStream := 'Mail Timestamp: ' +
              DateTimeToStr(MsgObject.Date);
            LogResult.LogType := ltInfo;
            WriteLog(LogResult);
          end;

          if SafeStop then
            exit;
        finally
          IMAPClient.UIDStoreFlags(TheUID, sdAdd, MsgObject.Flags + [mfDeleted]);
          MsgObject.Free;
        end;
        application.ProcessMessages;
        ProgressBar1.StepIt;
      end; // 1 to IMAPClient.MailBox.TotalMsgs
    end;
  finally
    IMAPClient.Disconnect;
    timeStop := GetTime;

    elapsedTime := secondsBetween(timeStart, timeStop);
    mailPerTime := totalInList / elapsedTime;
    Memo2.Lines.add('Total Mail Processed ' + IntToStr(totalInList));
    Memo2.Lines.add('Mail per second ' + floatToStr(mailPerTime));

    ackList.Free;
    btnHotStop.Enabled := false;
    btnDeleteClick(nil);
    StatusBar1.Panels[7].Text := 'Stopped';
    Memo1.Clear;
    if not SafeStop then
      Memo1.Lines.add
        ('All Acks have been Attacked!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
    else
      Memo1.Lines.add('Taking a breather....')
  end;
end;
Meta Mussel
  • 548
  • 1
  • 5
  • 19
  • 1
    `MsgObject.Headers.ConvertToStdValues(Memo1.Lines);` is useless since the `TIdMessage` was just created above it and so the `Headers` will be empty until `Retrieve()` is called later. Also, you are not checking the return value of `Retreive()` to know if the retrieval was successful before processing the `TIdMessage` data. And you don't need to call `GetUID()` and `UIDRetrieveFlags()`, as `Retrieve()` has already gotten the flags, they are in the `TIdMessage.Flags` property (and the UID is in the `TIdMessage.UID` property). – Remy Lebeau Aug 11 '17 at 21:49
  • And there is no point in using `GetUID()` just to get/set message flags, when you can use the equivalent methods that take a message number instead of a UID. – Remy Lebeau Aug 11 '17 at 21:51
  • Remy, I made the changes you suggested and edited my OP (mostly). Of course, it did not effect the Body issue. Body.Text shows '' for the value but I can see the body in the browser. Any suggestions of where to look next? – Meta Mussel Aug 14 '17 at 17:38
  • 1
    please reduce the code to a [mcve] (emphasis on **Minimal**), but more importantly please show the raw data for the email that is not decoding correctly. You are relying on `TIdMessage.Body` property but the text could be in a `TIdText` object within the `TIdMessage.MessageParts` collection instead, which you are completely ignoring. It all depends on the formatting of the email and how it is parsed. – Remy Lebeau Aug 14 '17 at 18:25
  • Thanks, I have it working now. – Meta Mussel Aug 16 '17 at 12:49

0 Answers0