TIdSMTP & TIdAttachmentMemory - электронная почта отклонена фильтром спама - PullRequest
0 голосов
/ 22 апреля 2019

Я пытаюсь отправить электронное письмо с вложением в формате PDF, сохраненное в поле BLOB, с использованием TIdSMTP.Для этого я использую TIdAttachmentMemory, но показанный код приводит к «отказу от спам-фильтра»;

  1. Пропуск IdMessage.ContentType := 'multipart/mixed' работает, но вложение не отправлено (или не получено?) - как и ожидалось.
  2. Оставляя это утверждение и создавая вложение из файла (как в закомментированном коде), все работает нормально (т. Е. Правильно полученное письмо с вложением).

Я явно что-то упускаю.Я подозреваю, что что-то в направлении вложения неправильно "закрыто" (то есть оставлено в неполном состоянии) или, возможно, неверный ContentType?

Все предложения приветствуются.Спасибо!

procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
  ms: TMemoryStream;
  Attachment: TIdAttachmentMemory;
  // Attachment: TIdAttachmentFile;
begin
  memStatus.Clear;

  IdSSLIOHandlerSocketOpenSSL.Destination := teHost.Text + ':587';
  IdSSLIOHandlerSocketOpenSSL.Host := teHost.Text;
  // IdSSLIOHandlerSocketOpenSSL.MaxLineAction := maException;
  IdSSLIOHandlerSocketOpenSSL.Port := 587;
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmUnassigned;
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;

  IdSMTP.Host := teHost.Text;
  IdSMTP.Port := 587;

  IdMessage.From.Address := teFrom.Text;
  IdMessage.Recipients.EMailAddresses := teTo.Text;
  IdMessage.Subject := teSubject.Text;
  IdMessage.Body.Text := memBody.Text;
  IdMessage.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));

  IdMessage.ContentType := 'multipart/mixed';

  if not sqlPDFPDF_Incasso.IsNull then
  begin
    ms := TMemoryStream.Create;
    try
      try
        TBlobField(sqlPDF.FieldByName('PDF_Incasso')).SaveToStream(ms);
        ms.Position := 0;
        Attachment := TIdAttachmentMemory.Create(IdMessage.MessageParts, ms);
        Attachment.ContentType := 'application/pdf';
        Attachment.FileName := 'Invoice.pdf';
      except
        on E: Exception do
          messageDlg('Error creating attachment' + #13#10 + E.Message, mtError, [mbOK], 0);
      end;
    finally
      ms.Free;
    end;
  end;

  // if FileExists(beAttachment.Text) then
  // Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, beAttachment.Text);

  Screen.Cursor := crHourGlass;
  try
    try
      IdSMTP.Connect;
      IdSMTP.Send(IdMessage);
      memStatus.Lines.Insert(0, 'Email sent - OK.');
    except
      on E: Exception do
        memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
    end;
  finally
    if assigned(Attachment) then
      Attachment.Free;
    if IdSMTP.Connected then
      IdSMTP.Disconnect(true);
    Screen.Cursor := crDefault;
  end;
end;

1 Ответ

1 голос
/ 23 апреля 2019

Вы не заполняете TIdMessage правильно (подробности см. в этой статье блога - ваш вариант использования будет попадать в раздел "HTML и не связанные с ним вложения и без простого текста", но замена HTML на обычный текст).

Короче говоря, если вы включите вложение, то для TIdMessage.ContentType следует установить значение 'multipart/mixed', но вам нужно поместить основной текст в объект TIdText в TIdMessage.MessageParts вместо TIdMessage.Body. И если вы не включите вложение, использовать TIdMessage.Body - это нормально, но вам нужно вместо TIdMessage.ContentType установить 'text/plain'.

Попробуйте это:

procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
  Text: TIdText;
  Attachment: TIdAttachmentMemory;
  Strm: TStream;
begin
  memStatus.Clear;

  IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmClient;
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;

  IdSMTP.Host := teHost.Text;
  IdSMTP.Port := 587;

  try
    IdMessage.Clear;

    IdMessage.From.Address := teFrom.Text;
    IdMessage.Recipients.EMailAddresses := teTo.Text;
    IdMessage.Subject := teSubject.Text;

    //if FileExists(beAttachment.Text) then
    if not sqlPDFPDF_Incasso.IsNull then
    begin
      IdMessage.ContentType := 'multipart/mixed';

      Text := TIdText.Create(IdMessage.MessageParts, nil);
      Text.Body.Text := memBody.Text;
      Text.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
      Text.ContextType := 'text/plain';

      //Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, beAttachment.Text);
      Attachment := TIdAttachmentMemory.Create(IdMessage.MessageParts);
      Attachment.ContentType := 'application/pdf';
      Attachment.FileName := 'Invoice.pdf';
      Strm := Attachment.PrepareTempStream;
      try
        TBlobField(sqlPDFPDF_Incasso).SaveToStream(Strm);
      finally
        Attachment.FinishTempStream;
      end;
    end else
    begin
      IdMessage.ContentType := 'text/plain';

      IdMessage.Body.Text := memBody.Text;
      IdMessage.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
    end;

    Screen.Cursor := crHourGlass;
    try
      IdSMTP.Connect;
      try
        IdSMTP.Send(IdMessage);
      finally
        IdSMTP.Disconnect;
      end;
      memStatus.Lines.Insert(0, 'Email sent - OK.');
    finally
      Screen.Cursor := crDefault;
    end;
  except
    on E: Exception do
      memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
  end;
end;

В качестве альтернативы, у Indy есть класс TIdMessageBuilderPlain, который может правильно настроить TIdMessage для вас (подробности см. в этой статье блога - ваш вариант использования подпадает под "Обычный текст и HTML"). и вложения: раздел «Только несвязанные вложения»):

uses
  ..., IdMessageBuilder;

procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
  Strm: TStream;
  Bldr: TIdMessageBuilderPlain;
begin
  memStatus.Clear;

  IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmClient;
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
  IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;

  IdSMTP.Host := teHost.Text;
  IdSMTP.Port := 587;

  try
    IdMessage.Clear;

    IdMessage.From.Address := teFrom.Text;
    IdMessage.Recipients.EMailAddresses := teTo.Text;
    IdMessage.Subject := teSubject.Text;

    Strm := nil;
    try
      Bldr := TIdMessageBuilderPlain.Create;
      try
        Bldr.PlainText.Text := memBody.Text;
        Bldr.PlainText.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));

        //if FileExists(beAttachment.Text) then
        if not sqlPDFPDF_Incasso.IsNull then
        begin
          //Bldr.Attachments.Add(beAttachment.Text);
          Strm := sqlPDFPDF_Incasso.DataSet.CreateBlobStream(sqlPDFPDF_Incasso, bmRead);
          Bldr.Attachments.Add(Strm, 'application/pdf').WantedFileName := 'Invoice.pdf';
        end;

        Bldr.FillMessage(IdMessage);
      finally
        Bldr.Free;
      end;
    finally
      Strm.Free;
    end;

    Screen.Cursor := crHourGlass;
    try
      IdSMTP.Connect;
      try
        IdSMTP.Send(IdMessage);
      finally
        IdSMTP.Disconnect;
      end;
      memStatus.Lines.Insert(0, 'Email sent - OK.');
    finally
      Screen.Cursor := crDefault;
    end;
  except
    on E: Exception do
      memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
  end;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...