Отправить письмо Delphi XE5

я пытаюсь отправить электронное письмо из Delphi XE5 (android) с компонентами Indy:

В форме у меня есть TIdSMTP и TIDMessage.

При создании формы:

testform:=Ttestform.create(self);
testform.show;

приложение останавливается, и я не знаю, что не так... я полагаю, что компоненты Indy несовместимы с Android...

  IdSMTP1.Heloname:='test';
  IdSMTP1.Host:='smtp.gmail.com';
  IdSMTP1.Username:='[email protected]';
  IdSMTP1.Port:=465;
  IdSMTP1.Password:='pass';

  if IdSMTP1.Connected=True then IdSMTP1.Disconnect;

  IdMessage1.clear;
  IdMessage1.From.Text :='Testing';
  IdMessage1.BccList.EMailAddresses :='[email protected]';
  IdMessage1.Priority := mpHigh;
  IdMessage1.Sender.Text:='Umail';
  IdMessage1.Subject := 'Subject';
  IdMessage1.Body.Add('test');
  IdSMTP1.Connect;
  Try
    IdSMTP1.Send(IdMessage1);
  except
  End;

Кто-нибудь этим пользуется?!

Приложение Form Dont SHOW остановлено... См. полный исходный код здесь http://pastebin.com/iGtJrHHs


person quimdotractor    schedule 02.10.2013    source источник
comment
Вам не хватает замыкающей кавычки в строке IdMessage1.BccList.EMailAddresses :='[email protected];;.   -  person Marcus Adams    schedule 02.10.2013
comment
Хотя я не могу заставить IdSMTP что-либо делать, кроме как сделать мое приложение не отвечающим (1-е поколение Nexus 7), когда я нажимаю кнопку «Отправить почту». Форма отображается просто отлично при запуске приложения. Возможно, вы можете начать с пустого приложения, добавлять по одному компоненту и начинать заново.   -  person Anthony Eischens    schedule 02.10.2013
comment
Затем вам нужно отладить ваше приложение. Сначала подтвердите, виноват ли TIdSMTP, а не просто предполагайте, что это так. Если он виноват (в чем я сомневаюсь), вы можете проследить его исходный код, чтобы найти фактическое зависание. Или вы можете просто изменить свой код, чтобы удалить TIdSMTP из TForm и вместо этого переместить его в рабочий поток (что вы должны сделать в любом случае, поскольку вы никогда не должны блокировать основной поток).   -  person Remy Lebeau    schedule 03.10.2013


Ответы (5)


Это не прямой ответ на проблему с Indy, но если вы решили сменить тактику и использовать встроенные параметры создания электронной почты на Android, вы можете использовать такой код:

uses
  FMX.Helpers.Android,
  Androidapi.JNIBridge,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText;
...
procedure CreateEmail(const Recipient, Subject, Content: string);
var
  Intent: JIntent;
  Recipients: TJavaObjectArray<JString>;
begin
  Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_SEND);
  Recipients := TJavaObjectArray<JString>.Create(1);
  Recipients.Items[0] := StringToJString(Recipient);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_EMAIL, Recipients);
  Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(Subject));
  Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(Content));
  Intent.setType(StringToJString('plain/text'));
  SharedActivity.startActivity(TJIntent.JavaClass.createChooser(Intent,
    StrToJCharSequence('Which email app?')));
end;

Я оставлю это кому-то другому, чтобы предложить решение проблемы с Инди.

person blong    schedule 02.10.2013
comment
я принимаю это решение для решения проблемы, потому что Indy IdSMTP несовместим с Android. - person quimdotractor; 03.10.2013
comment
Да, TIdSMTP совместим с Android. Другие люди успешно использовали его. Вы первый человек, которого я видел, сообщающий о проблеме с его использованием. - person Remy Lebeau; 03.10.2013
comment
У меня точно такая же проблема. @Remy, может быть, ты опубликуешь свое решение? Я создаю TIdMessage в коде, и когда я меняю его свойства, приложение зависает (не отвечает ни на один клик). На данный момент я возьму решение blong. - person mad; 09.01.2014
comment
@mad: простая установка значения свойства не может привести к зависанию. Происходит что-то еще. Какая ТОЧНАЯ строка кода зависает? - person Remy Lebeau; 09.01.2014

пользователь 1147833;

вы должны выполнить операцию аутентификации после подключения к серверу.

Просто переключитесь на свой код;

IdSMTP1.Connect;
IdSMTP1.Authenticate;
  Try
    IdSMTP1.Send(IdMessage1);
  except
  End;
person ikutluay    schedule 02.10.2013
comment
Я отправляю много писем с Indy, и если вы хотите, я могу поделиться подробным кодом. Но он разработан для моего процесса и не совместим с Android. Но похоже, что ваше приложение остановлено, потому что оно не аутентифицировано и не может продолжаться таким образом. Я думаю, что ваша ошибка в коде проста и просто добавьте одну строку в ваш код. Пожалуйста, не стесняйтесь присылать нам код ошибки, чтобы понять, что происходит. - person ikutluay; 02.10.2013
comment
не работает, спасибо. Форма останавливается перед показом ... так что это не ошибка аутентификации, а проблема в IdSMTP (я думаю) - person quimdotractor; 02.10.2013
comment
@ user1147833, если вы отправляете при создании, то это все еще имеет смысл. - person Marcus Adams; 02.10.2013
comment
нет, я не отправляю в шоу, очевидно... находится в кнопке, а форма не отображается. - person quimdotractor; 02.10.2013
comment
TIdSMTP.Send() вызывает TIdSMTP.Authenticate() внутри, поэтому нет необходимости вызывать его явно. - person Remy Lebeau; 02.10.2013
comment
я не могу, потому что форма не отображается... я думаю, что это конструктор компонента, потому что, когда я вызываю formender:=Tformsender.create(self); формыender.show; приложение не отвечает. просто остановить - person quimdotractor; 02.10.2013
comment
В TIdSMTP (или любом другом компоненте Indy) нет ничего, что должно было бы препятствовать отображению формы, если только вы не выполняете операцию блокировки сокета внутри события OnShow формы. - person Remy Lebeau; 03.10.2013

Убран ряд элементов, ни один из которых не поможет, если ваша форма на самом деле не отображается.
Приведенное ниже сообщение успешно отправлено с Nexus 7 1-го поколения с использованием SMTP-сервера, требующего аутентификации и работающего на порту 25.

Если вы действительно подключаетесь к порту 465 на серверах Google, вы должны использовать шифрование, к которому этот код не относится.

Простые присваивания IdMessage1.From.Text := 'бла-бла'; Не работали, поэтому вы увидите, что я заменил IdMessage1.From.Address и аналогичные свойства на другие свойства IdMessage1.

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdExplicitTLSClientServerBase, IdMessageClient, IdSMTPBase, IdSMTP, IdMessage,
  FMX.StdCtrls, FMX.Edit;

type
  Ttestform = class(TForm)
    IdSMTP1: TIdSMTP;
    IdMessage1: TIdMessage;
    btnMessageSend: TButton;
    edtUsername: TEdit;
    edtPassword: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    edtFrom: TEdit;
    Label3: TLabel;
    edtTo: TEdit;
    Label4: TLabel;
    edtServer: TEdit;
    Label5: TLabel;
    edtPort: TEdit;
    Label6: TLabel;
    procedure btnMessageSendClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  testform: Ttestform;

implementation

{$R *.fmx}

procedure Ttestform.btnMessageSendClick(Sender: TObject);
var
  intPort: Integer;
begin
  ShowMessage('In button click');
  IdSMTP1.Heloname:='test';
  IdSMTP1.Host:=edtServer.Text;
  IdSMTP1.Username:=edtUsername.Text;
  intPort := 25;
  ShowMessage('Before strtoint');
  TryStrToInt(edtPort.Text, intPort);
  ShowMessage('After strtoint');
  IdSMTP1.Port:= intPort;
  IdSMTP1.Password:=edtPassword.Text;

  if IdSMTP1.Connected=True then IdSMTP1.Disconnect;
  IdMessage1.Clear;
  IdMessage1.From.Address := edtFrom.Text;
  IdMessage1.Recipients.Add;
  IdMessage1.Recipients.Items[0].Address := edtTo.Text;
  IdMessage1.Priority := mpHigh;
  IdMessage1.Sender.Address:=edtFrom.Text;
  IdMessage1.Subject := 'Subject';
  IdMessage1.Body.Add('test');
  IdSMTP1.Connect;
  IdSMTP1.Send(IdMessage1);
end;

end.
person Anthony Eischens    schedule 02.10.2013
comment
пожалуйста, посмотрите ссылку на полный исходный код... форма не отображается, и я не могу нажать кнопку подключения - person quimdotractor; 03.10.2013

Инди совместим с Android. Это не проблема Android, это проблема конфигурации.

Порт 465 Gmail использует неявный SSL для шифрования соединения. При подключении к порту 465 сервер ожидает, что ваше приложение инициирует рукопожатие SSL, чтобы установить сеанс SSL, прежде чем можно будет обмениваться данными SMTP.

Перед подключением необходимо прикрепить компонент TIdSSLIOHandlerOpenSSL к свойству TIdSMTP.IOHandler, а затем установить для свойства TIdSMTP.UseTLS значение utUseImplicitTLS. Без этого TIdSMTP не отправит подтверждение SSL. Он просто будет ждать SMTP-приветствия сервера, которое сервер не отправит до тех пор, пока сначала не будет установлен сеанс SSL. Таким образом, возникает взаимоблокировка, если вы не установите для свойства TIdSMTP.ReadTimeout не бесконечное значение, чтобы TIdSMTP.Connect() могло вызвать исключение, если оно не получает приветствие SMTP.

person Remy Lebeau    schedule 02.10.2013
comment
я перехожу на порт 25, и проблема та же... форма не отображается - person quimdotractor; 03.10.2013
comment
При подключении к порту 25 клиент должен выполнить команду STARTTLS после подключения и получения SMTP-приветствия перед входом в систему. В случае TIdSMTP это достигается установкой для свойства UseTLS значения utUseExplicitTLS. - person Remy Lebeau; 03.10.2013

Перед развертыванием на устройстве Android запустите на платформе Win32, чтобы проверить, все ли в порядке. Не забудьте поместить OpenSSL DLL (libeay32.dll и ssleay32.dll) в один и тот же каталог, но это не подходит для Android. Вот мой код.

procedure TForm1.Button1Click(Sender: TObject);
begin
with IdMessage1 do
begin
  Recipients.EMailAddresses := '[email protected]';
  From.Address              := '[email protected]';
  From.Name                 := 'Self';
  CCList.EMailAddresses     := '';
  BccList.EMailAddresses    := '';
  Priority                  := mpNormal;
  Subject                   := 'Test Mail Subject';
  Body.Add('Test Mail Body');
end;

with IdSMTP1 do
begin
  Host      := 'smtp.gmail.com';
  Username  := 'xxxxxxx';
  Password  := 'yyyyyyy';
  IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Self);
  Port      := 465;
  UseTLS    := utUseImplicitTLS;

  try
  Connect;
  except
  end;

  if not Connected then
  begin
    Showmessage('Error');
    Exit;
  end;

  try
  Send(IdMessage1);
  finally
  Disconnect;
  end;

 end;
end;
person user3741041    schedule 16.06.2014
comment
спасибо за код, но этот код отлично работает на моем компьютере, но на других машинах будет возникать ошибка ... почему это так? - person Armin Taghavizad; 12.10.2014