最简单的发送电子邮件方式是什么?

13

我想从我的Delphi程序中发送简单的邮件消息。更具体地说,如果我的程序遇到异常,我想提供通过用户提供的任何指定电子邮件地址发送错误的选项,当然,能够发送任何情况下的电子邮件本身就会很有益。能够发送附件是一个额外的好处,但不是必需的。

我尝试过许多在线找到的示例,但大多数似乎都不起作用。其中一些需要参数,如SMTP服务器等,但如果用户可以自由输入他们自己的电子邮件地址,那么我的程序如何确定这些参数呢?另外,我没有在我的计算机上安装默认的电子邮件客户端,因此如果我无法从我的程序中发送电子邮件,那么使用我的程序的任何其他人都会遇到同样的问题。

所以基本上我在问:

  • 如何发送电子邮件
  • 不需要附件,但会有它的优点
  • 如何处理SMTP服务器、端口号等事项?
  • 如果没有安装默认的电子邮件客户端,该如何处理

希望我的帖子容易理解。

谢谢

5个回答

5
如果您希望程序在异常发生时向您发送电子邮件,您应该查看MadExcept。它会自动为您执行此操作,并包括完整的堆栈跟踪和其他有用的调试信息。

是的,但如果我知道如何发送电子邮件,它将在其他情况下非常有用 :) - user741875
那么你应该编辑你的问题。考虑一下其他人,Craig,他们会来看的。 - Warren P
我会编辑它,对于任何困惑感到抱歉。 - user741875

3
我将从可能的解决方案开始,然后解释为什么其他替代方案在最好的情况下都存在问题:
可能的解决方案:
1. 不要从客户端计算机发送电子邮件,使用 Web 服务传递消息。无论您的网站使用什么技术,它都可以处理已发布的表单并发送电子邮件。只需将用户的问题 POST 到您的 Web 服务,让您的 Web 服务使用电子邮件将其发送给您或将其保存到数据库中。如果用户认为他已连接到互联网,他可能会这样说,因为他的浏览器工作了,但是这仅表示 HTTP 正常工作:SMTP 可能被公司防火墙或 ISP 阻止。这是我首选的解决方案。
2. 使用您的 SMTP 服务器和凭据发送电子邮件。从用户地址发送电子邮件非常不可靠。您可以在“回复”头中包含用户的电子邮件地址,或者简单地将其放在消息正文中。您可以使用 Indy 组件来执行此操作,因为这是您的 SMTP 服务器和凭据,您知道所有细节。如前面所述,这可能会失败,因为用户的防火墙或 ISP 的防火墙可能会阻止 SMTP。
关于 SMTP:
首先,对 SMTP 协议本身进行一些介绍,因为其他所有内容都基于此:
1. SMTP 是发送电子邮件的协议。有其他特定于实现的协议,但所有电子邮件服务器都需要实现 SMTP。
2. SMTP 设计之前没有垃圾邮件。它允许任何计算机将电子邮件发送到任何服务器。理论上不需要任何身份验证即可发送电子邮件消息,并且服务器的 SMTP 服务器地址存储在 DNS 中作为 MX 记录。
3. SMTP 本身没有包括验证发件人的方法,也没有尝试检查用户是否真的是“发件人”字段中的那个人。
从用户的电子邮件地址发送电子邮件存在什么问题:
从用户地址发送电子邮件的第一个选项是使用本地安装的客户端和自动化,因此他们会看到一个填好的 Outlook(或 Firefox 或其他)电子邮件表单,只需点击“发送”即可。但是你说你希望你的解决方案即使在没有本地电子邮件安装的情况下也能工作,所以这不是一个选项。
您提到希望通过仅询问用户的电子邮件地址(没有服务器详细信息,我假设没有用户名和密码)来实现此目标。SMTP 协议实际上允许这样做,因为它没有内置机制来验证发件人。垃圾邮件发送者利用了这一点,称之为“欺骗发件人地址”。为了防止这种情况发生,发生了两件事:
  • SMTP主机不再接受来自任何人的电子邮件,它们会尝试对发送SMTP服务器进行身份验证。换句话说,您的 SMTP服务器将拒绝您发送给自己的伪造电子邮件!解决此问题的方法是使用SMTP中继。但是...
  • SMTP中继不再中继来自未知用户的电子邮件!SMTP本身并不提供任何身份验证机制,但通常的解决方法是先阅读电子邮件(因为该部分需要身份验证),然后再发送电子邮件。这由您可能正在使用的发送SMTP组件自动完成,但无论如何,这都需要用户名和密码。

如果这还不够,请换一种思路考虑:您是否希望任何知道您的电子邮件地址的人都能够使用您的电子邮件地址发送电子邮件?


2

JEDI Code Library中的JclMapi单元包含两个使用已安装的MAPI客户端的简单方法:

function JclSimpleSendMail(const Recipient, Name, Subject, Body: AnsiString;
  const Attachment: TFileName = ''; ShowDialog: Boolean = True; ParentWND: THandle = 0;
  const ProfileName: AnsiString = ''; const Password: AnsiString = ''): Boolean;

并且

function JclSimpleBringUpSendMailDialog(const Subject, Body: AnsiString;
  const Attachment: TFileName = ''; ParentWND: THandle = 0;
  const ProfileName: AnsiString = ''; const Password: AnsiString = ''): Boolean;

无需在Delphi中配置服务器等 - 使用已安装的客户端的设置即可。
然而,如果未安装任何邮件客户端,则此简单解决方案无法使用。很抱歉我回答得太快了。
另一个选项是提供一个公共Web服务器(我使用Google App Engine实现),可以通过发送HTTP请求从Delphi应用程序作为电子邮件网关使用。这可以使用Indy完成,并且由于具有Internet访问权限的客户通常能够执行HTTP请求,因此不需要特殊配置,因为SMTP客户端并不总是允许通过企业防火墙。
madExcept库提供相同的传输方法(通过HTTP发送),因为它只需要应用程序中定义的服务器地址作为常量。

我尝试了您发布的方法,但不幸的是我收到了以下信息:“没有与所请求的操作执行相关联的电子邮件程序。请安装电子邮件程序或者如果已经安装,请在默认程序控制面板中创建一个关联。” 看来我需要安装Outlook。 - user741875
1
我喜欢这个答案,因为它使用默认电子邮件程序的配置。你可以使用这个来获取正确的服务器名称,然后使用 @Tim 的答案作为备选方案。 - Johan

1

我认为发送电子邮件最简单的方法是使用Windows协作数据对象(CDO)。另一种方法是使用Indy组件,但我不喜欢它巨大的二进制文件大小。

在使用CDO之前,请从c:\ windows \ system32 \ cdosys.dll导入类型库。以下示例显示如何使用CDO发送电子邮件:

uses CDO_TLB;

var M: IMessage;
    s: string;
begin
  M := CoMessage.Create;
  M.From := 'from-email@host.com';
  M.To_ := 'to-email@host.com';
  M.Subject := 'This is subject';
  M.TextBody := 'This is text body';

  s := 'http://schemas.microsoft.com/cdo/configuration/';
  with M.Configuration.Fields do begin
    Item[s + 'sendusing'].Value := cdoPostUsingPort;
    Item[s + 'smtpserver'].Value := 'smtp.host.com';
    Item[s + 'smtpauthenticate'].Value := cdoBasic;
    Item[s + 'sendusername'].Value := 'user_name';
    Item[s + 'sendpassword'].Value := 'password';
    Item[s + 'smtpserverport'].Value := 587;
    Item[s + 'smtpusessl'].Value := False;
    Item[s + 'smtpconnectiontimeout'].Value := 5;  // default is 30 seconds
    Update;
  end;

  try
    M.Send;
    // success
  except
    // fail
    on E: Exception do
      ShowMessage(E.Message);
  end;
end;

1
如果您知道您的电子邮件主机的名称,请使用TidSMTP组件。这是indy客户端的一部分。
然后填写您的信息并调用此组件。
Email.QuickSend('mail.YourEmailHost.com','Title','Addressed To',
                'Where_the_email_looks_like_it_came_from@YourDomain.com','EmailText');

如果我的用户可以自由输入他们的电子邮件地址,那么我就不知道主机,所以我必须需要解释它或其他什么。 - user741875
不要完全相信我的话,但我认为如果你有一个有效的主机可以使用,那么你可以让任何使用你的程序的人使用你的电子邮件主机。我还没有测试过这个,但我会调查一下。如果这确实可行,那么你只需要让他们输入电子邮件地址即可。 - Tim
如果我理解正确的话,这有点像是从我的电子邮件主机中转电子邮件,发送到收件人的任何目标地址。 - user741875

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接