【问题标题】:Send email Delphi XE5发送电子邮件 Delphi XE5
【发布时间】:2013-10-08 18:46:27
【问题描述】:

我正在尝试使用 Indy 组件从 Delphi XE5 (android) 发送电子邮件:

在表单中我有一个TIdSMTP 和一个TIDMessage

表单创建时:

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

应用程序停止,我不知道出了什么问题...我想 Indy 组件在 Android 中不兼容...

  IdSMTP1.Heloname:='test';
  IdSMTP1.Host:='smtp.gmail.com';
  IdSMTP1.Username:='umail@gmail.com';
  IdSMTP1.Port:=465;
  IdSMTP1.Password:='pass';

  if IdSMTP1.Connected=True then IdSMTP1.Disconnect;

  IdMessage1.clear;
  IdMessage1.From.Text :='Testing';
  IdMessage1.BccList.EMailAddresses :='umail@gmail.com';
  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

【问题讨论】:

  • 您在IdMessage1.BccList.EMailAddresses :='umail@gmail.com;; 行缺少尾随引号。
  • 当我点击“发送邮件”按钮时,除了让我的应用程序无响应(第一代 Nexus 7)之外,我无法让 IdSMTP 做任何事情。该表单在应用程序启动时显示得很好。也许您可以从一个空白应用程序开始,一次添加一个组件,然后重新开始。
  • 然后你需要调试你的应用程序。首先确认 TIdSMTP 是否有错误,不要只是假设它是错误的。如果它有问题(我怀疑),那么您可以跟踪其源代码以找到实际的挂起。或者,您可以简单地重新设计您的代码以从 TForm 中删除 TIdSMTP,并将其移至工作线程(无论如何您都应该这样做,因为您永远不应该阻塞主线程)。

标签: android delphi smtp indy delphi-xe5


【解决方案1】:

这不是 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;

我将把它留给其他人来提供解决 Indy 问题的方法。

【讨论】:

  • 我接受此解决方案来管理问题,因为 Indy IdSMTP 与 android 不兼容。
  • 是的,TIdSMTP 与 Android 兼容。其他人已经成功使用它。你是我见过的第一个报告使用它的人。
  • 我也有同样的问题。 @Remy 也许您发布了您的解决方案?我在代码中创建 TIdMessage ,当我更改它的属性时,应用程序会挂起(对任何点击都不响应)。目前我会采取 blong 的解决方案。
  • @mad:仅设置属性值不会导致挂起。其他事情正在发生。哪一行代码挂了?
【解决方案2】:

用户1147833;

您应该在连接到服务器后进行身份验证操作。

只需切换到您的代码;

IdSMTP1.Connect;
IdSMTP1.Authenticate;
  Try
    IdSMTP1.Send(IdMessage1);
  except
  End;

【讨论】:

  • 我用 indy 发送了很多电子邮件,如果你希望我可以分享详细的代码。但它是为我的进程开发的,与 Android 不兼容。但似乎您的应用程序已停止,因为它没有经过身份验证并且无法以这种方式继续。我认为您的代码错误很简单,只需在代码中添加一行。请随时向我们发送“错误代码”,以了解发生了什么。
  • 不工作,谢谢。表单在显示之前停止......所以不是身份验证失败,而是 IdSMTP 中的问题(我认为)
  • @user1147833,如果您在创建中进行发送,那么这仍然有意义。
  • 不,我显然没有发送显示...在按钮中并且表单不显示。
  • TIdSMTP.Send() 在内部调用 TIdSMTP.Authenticate() ,所以不需要显式调用。
【解决方案3】:

清理了一些项目,如果您的表单没有真正显示,这些都无济于事。
下面使用需要身份验证并在端口 25 上运行的 SMTP 服务器成功地从第一代 Nexus 7 发送了一条消息。

如果您真的要连接到 Google 服务器上的端口 465,则必须使用此代码未解决的加密。

IdMessage1.From.Text := 'blah blah'; 的简单赋值没有工作,所以你会看到我用 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.

【讨论】:

  • 请查看完整源代码的链接...表单不显示,我无法点击“连接”按钮
【解决方案4】:

Indy 与 Android 兼容。这不是安卓问题,是配置问题。

Gmail 的 465 端口使用隐式 SSL 来加密连接。连接到端口 465 后,服务器希望您的应用在交换任何 SMTP 数据之前启动 SSL 握手以建立 SSL 会话。

在连接之前,您必须将TIdSSLIOHandlerOpenSSL 组件附加到TIdSMTP.IOHandler 属性,然后将TIdSMTP.UseTLS 属性设置为utUseImplicitTLS。 否则,TIdSMTP 将不会发送 SSL 握手。它将简单地等待服务器的 SMTP 问候语,服务器在 SSL 会话首先建立之前不会发送该问候语。因此会发生死锁,除非您将 TIdSMTP.ReadTimeout 属性设置为非无限值,以便 TIdSMTP.Connect() 在未收到 SMTP 问候时引发异常。

【讨论】:

  • 我改到 25 端口,问题还是一样...表单不显示
  • 连接到端口 25 时,客户端必须在连接并检索 SMTP 问候语后发出STARTTLS 命令,然后才能登录。在TIdSMTP 中,通过设置其UseTLS 属性来完成改为utUseExplicitTLS
【解决方案5】:

在部署到Android设备之前,在Win32平台上运行检查是否OK。 记得把 OpenSSL DLL(libeay32.dll 和 ssleay32.dll)放在同一个目录下,但是 Android 不行。 这是我的代码。

procedure TForm1.Button1Click(Sender: TObject);
begin
with IdMessage1 do
begin
  Recipients.EMailAddresses := 'test@gmail.com';
  From.Address              := 'test@gmail.com';
  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;

【讨论】:

  • 感谢代码,但这段代码在我的电脑上运行良好,但在其他机器上会出现错误...这是为什么呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-24
  • 2013-08-26
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多