顯示具有 [Indy] 標籤的文章。 顯示所有文章
顯示具有 [Indy] 標籤的文章。 顯示所有文章

2015/03/10

Delphi XE7使用Indy 10.6.1連結Gmail SMTP


緣起

我在KTOP中回答「xe6 使用gmail的問題」這個主題,因為程式碼編排有問題,故在這裡另外轉貼。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
unit Unit1;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdExplicitTLSClientServerBase, IdSMTP, IdSSLOpenSSL,
  IdMessage, IdAttachmentFile, Vcl.StdCtrls;
 
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
/// <summary>
/// Sends an email using the specified SMTP server.
/// </summary>
/// <param name="sendTo">The email address of the recipient.</param>
/// <param name="subject">The subject of the email.</param>
/// <param name="body">The body of the email.</param>
/// <param name="attachFiles">A TStringList containing file paths to be attached to the email. Can be nil if no attachments are required.</param>
/// <param name="smtpHost">The hostname or IP address of the SMTP server.</param>
/// <param name="smtpPort">The port number of the SMTP server.</param>
/// <param name="smtpUser">The username to authenticate with the SMTP server.</param>
/// <param name="smtpPass">The password to authenticate with the SMTP server.</param>
/// <param name="tls">The type of TLS encryption to use. Can be utNoTLSSupport if TLS is not supported by the SMTP server.</param>
/// <returns>True if the email was sent successfully, false otherwise.</returns>    
    function SendEmail(sendTo: string;
                    subject: string;
                    body: string;
                    attachFiles: TStringList;
                    smtpHost: string;
                    smtpPort: Integer;
                    smtpUser: string;
                    smtpPass: string;
                    tls: TIdUseTLS): boolean;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  SendEmail( 'mybuddy@example.com', // 目的地E-Mail
                    'This is the subject',
                    'This is the body of the email....',
                    nil,
                    'smtp.gmail.com',
                    587,
                    'myusername@gmail.com', // 登入帳號
                    'mypassword'{ 登入密碼 }, utUseExplicitTLS);
end;
 
function TForm1.SendEmail(sendTo, subject, body: string;
  attachFiles: TStringList; smtpHost: string; smtpPort: Integer; smtpUser,
  smtpPass: string; tls: TIdUseTLS): boolean;
var
    smtp: TIdSmtp;
    ssl: TIdSSLIOHandlerSocketOpenSSL;
    msg: TIdMessage;
    i: Integer;
begin
    smtp:=TIdSmtp.Create(nil);
    ssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    msg:=TIdMessage.Create(nil);
    try
 
        try
            smtp.Host:=smtpHost;
            smtp.Port:=smtpPort;
            smtp.Username:=smtpUser;
            smtp.Password:=smtpPass;
 
            //smtp.OnConnected :=IdSMTP1Connected;
            //smtp.OnDisconnected :=IdSMTP1Disconnected;
            //smtp.OnFailedRecipient :=IdSMTP1FailedRecipient;
            //smtp.OnStatus :=IdSMTP1Status;
            //smtp.OnTLSNotAvailable :=IdSMTP1TLSNotAvailable;
            //smtp.OnWork :=IdSMTP1Work;
 
            if not (tls=utNoTLSSupport) then begin
                ssl.Destination:=smtpHost + ':' + IntToStr(smtpPort);
                ssl.Host:=smtpHost;
                ssl.Port:=smtpPort;
                ssl.SSLOptions.Method:=sslvTLSv1;
 
                //ssl.OnStatusInfo:=IdSSLIOHandlerSocketOpenSSL1StatusInfo;
                //ssl.OnGetPassword:=IdSSLIOHandlerSocketOpenSSL1GetPassword;
                //ssl.OnStatus:=IdSSLIOHandlerSocketOpenSSL1Status;
 
                smtp.IOHandler:=ssl;
                smtp.UseTLS:=tls;
            end;
 
            msg.Recipients.EMailAddresses := sendTo;
            msg.Subject:=subject;
            msg.Body.Text:=body;
 
            if(Assigned(attachFiles)) then begin
                for i := 0 to attachFiles.Count - 1 do begin
                   if FileExists(attachFiles[i]) then
                        TIdAttachmentFile.Create(msg.MessageParts, attachFiles[i]);
                end;
            end;
 
            smtp.Connect;
            smtp.Send(msg);
            smtp.Disconnect;
 
            result:=true;
        finally
            msg.Free;
            ssl.Free;
            smtp.Free;
        end;
    except
       result:=false;
    end;
end;
 
end.

結論:

使用 Indy 10.6.1 連接 Gmail SMTP 並成功發送和接收電子郵件。它在 Delphi XE7 中運作正常,可以作為開發人員實現電子郵件發送功能的參考。

 和你分享。😉

參考資料來源:

2014/12/02

Indy 操作 SMTP 發生 "Could not load SSL library"?

在 Indy 操作 SMTP 時,Delphi 跳出「Could not load SSL library」的訊息。

去 Win32 OpenSSL 網站下載個 「Light」版來安裝,就能解決這個問題了!

另外,這個網站有更詳盡的解說:"Cannot load SSL Library" using Delphi XE7

2018/05/04 更新:
要取得編譯給 Indy 用的 SSL 檔案才行。連結置於「延伸閱讀」裡。

延伸閱讀:

2012/11/26

2012/09/25

Indy10 IdHTTP對非英文語的處理方式(泛中文處理)

這陣子想從網路上下載一些文件,URL大致上像下面這句:

「sUrl := http://www.DelphiCpp.com/我愛Delphi.txt」

使用 IdHTTP.Get(sUrl, ms) 方法卻怎麼也抓不到,可是也沒有Exception…

李組長眉頭一皺,發現案情並不單純。

於是請了Google大神拜了一下,也發現不少災情。

请问Delphi7怎么解决Indy发送中文字符的问题
Thread: IdHTTP and æøå ??

發現共通點都是靠「TIdTextEncoding」來解決問題
所以原先的作法就修改成這樣:

2011/09/28

Indy -- 專業的Blocking

Indy (Internet Direct)與Dbexpress在Delphi中是我最喜歡的技術類型。
今天來說說它的特色之一 -- Blocking

很多人都會很好奇,SocketServer和idTCPServer主要的差異在於一個預設為non-Blocking,另一個則是恆為Blocking,但這兩者之間有什麼樣的不同呢?

我不知道!(被毆)

2011/05/07

很有意思的Indy連結,下次有時間再來玩玩看

我記得 Delphi 2009 內附的 Indy 好像是 10.2.3 版,這對想寫網路程式的工程師很有幫助

Delphi2009的Indy全接触之TCP篇
Delphi2009的Indy全接触之UDP篇

有時間再來試試吧!

2010/08/13

要用indy作個網路聊天室?要有踩地雷的心理準備……

前一陣子又想練習一下 Indy 元件組,不經意發現

Sever Side Chat Application with Borland Delphi/Indy
有提供範例!


馬上下載它的範例來看看。


想不到code亂就算了,還error一堆


debug到快翻過去了,還沒搞定!


D7+Indy 10.0.52版本


用法與10.2.3差了一大截!


練習痛苦指數可說是破表呀!


掃雷ing

2009/11/25

Upgrading to Indy 10 (從Indy9升級到Indy10)

出處:Upgrading to Indy 10

Upgrading to Indy 10

Abstract: This session covers the changes made to Indy 10 and how to quickly port existing code. It also covers the advantages of Indy 10 and why you should port your code. While performance and other demonstrations are shown, this session is a practical overview and does not focus on demo code.
Chad Hower works for Atozed Software, and is the original author of Indy and IntraWeb. When not programming, he likes to bike, kayak, ski, drive, or just be outdoors. Chad is an ex-patriate who spends his summers in St. Petersburg, Russia, winters in Cyprus, and travels extensively year round.

2009/07/12

TIdSysLog Class - SendMsg篇(四)

這次所講的是SendLogMessage內的另一參數:Severity
Indy中是這麼解釋的:
Indicates the severity of the Syslog message.
這封訊息的嚴重性。

結構如下:

TIdSyslogSeverity = (
slEmergency,
slAlert,
slCritical,
slError,
slWarning,
slNotice,
slInformational,
slDebug
);

嚴重性由上而下,由重到低,依此類推。
TIdSysLog Class - SendMsg篇(三)一樣,提到轉為文字的函式。

資料來源:TIdSyslogSeverity enumeration

2009/07/09

TIdSysLog Class - SendMsg篇(三)

上次我們看到SendMessage / SendLogMessage中有其它的參數,我們再來研究一下它們的內容吧!
這次我們先從TIdSyslogFacility說起吧
顧名思義,這單字就是設備。
原文是這麼解釋的:
Indicates the facility that caused the message to be generated.
送出此訊息的設備別。

在Syslog中,除了訊息以外,再來就是發送訊息的來源,方便我們使用者做後續的追蹤。

結構大致如下

TIdSyslogFacility = (
sfKernel,
sfUserLevel,
sfMailSystem,
sfSystemDaemon,
sfSecurityOne,
sfSysLogInternal,
sfLPR,
sfNNTP,
sfUUCP,
sfClockDaemonOne,
sfSecurityTwo,
sfFTPDaemon,
sfNTP,
sfLogAudit,
sfLogAlert,
sfClockDaemonTwo,
sfLocalUseZero,
sfLocalUseOne,
sfLocalUseTwo,
sfLocalUseThree,
sfLocalUseFour,
sfLocalUseFive,
sfLocalUseSix,
sfLocalUseSeven
);


上面提到的只是發送的部份,在接收的話就只會看到「01234…n」的數字。難道我們只能後續用switch的方式來轉換為文字嗎?
其實TIdSyslogFasility也提供了反向轉換的工具:
結構如下:

function FacilityToString(
AFac: TIdSyslogFacility
): string;


這樣傳送與接收就更趨完整了吧。

參考來源:TIdSyslogFacility

2009/07/08

TIdSysLog Class - SendMsg篇(二)

這次再介紹一下IdSysLog SendMessage的內容
基本上,如果捨SendMsg而就Send的話
那麼接收端就會收到單純的Message,TimeStamp就不會追加在Message前面。

而如果要用SendMessage而又不想加TimeStamp,呃…目前我還沒找到方法…如果我有找到的話再放上來吧



TIdSysLog.SendMessage
Sends a message to the loggin daemon.

procedure SendMessage(const AMsg: TIdSysLogMessage; const AAutoTimeStamp: Boolean = true); overload;
procedure SendMessage(const AMsg: String; const AFacility: TidSyslogFacility; const ASeverity: TIdSyslogSeverity); overload;
procedure SendMessage(const AProcess: String; const AText: String; const AFacility: TidSyslogFacility; const ASeverity: TIdSyslogSeverity; const AUsePID: Boolean = False; const APID: Integer = -1); overload;

Parameters

const AMsg: TIdSysLogMessage

Syslog message instance or string.
實體Syslog message 或是 某一字串


const AAutoTimeStamp: Boolean = true

Add time stamp to the message.
增加time stamp到欲輸出的訊息

const AFacility: TidSyslogFacility

The facility for the logged message.
發送訊息的場所

const ASeverity: TIdSyslogSeverity

The severity of the logged message.
發送訊息的重要性

const AProcess: String

The process name.
發送訊息的程序名

const AText: String

Descriptive text for the syslog entry.
可讓syslog發送的描述性文字

const AUsePID: Boolean = False

Use a process ID.
是否使用程序ID (Handle),預設為「否」

const APID: Integer = -1

Process ID for the syslog entry.
可讓syslog發送的程序ID

後面的說明…有點煩雜
主要是在說明SendMessage重載了TIdSyslog後做了哪些的加強及擴充,有興趣的可以再自己翻一下底下的內容。

Description
SendMessage is an overloaded procedure in TIdSysLog used to form and transmit a message destined for the logging daemon.
One variant of SendMessage sends the existing TIdSyslogMessage instance identified in AMsg to the logging daemon. AAutoTimeStamp indicates if the current date and time should be applied to the TIdSyslogMessage.Timestamp property prior to transmission. This variant calls Send using the encode value for the message.

Other variants of SendMessage construct a new TIdSyslogMessage instance and populate it's values using the arguments specified for the procedure. Each of these overloaded procedure calls the SendMessage variant that uses the existing TIdSyslogMessage instance.

2009/07/07

TIdSysLog Class - SendMsg篇(一)

TIdSysLog Class
---------------------------------
TIdSyslog SendLogMessage --Indy 10.x
TIdSyslog SendMessage --Indy 9.x (實際應用是SendMsg)
---------------------------------

Exsample:
//This is C++ Code
IdSysLog1->SendMsg("Test HI!",sfUserLevel,slInformational);


Sends a message to the logging daemon. --Indy10.1.5
Sends a message to the loggin daemon --Indy9........(看出哪裡錯了嗎?)
對Syslog Server發送一個訊息。

logging daemon 原文應該是翻成 「登錄守護靈」??
但實際指的就是接收 Syslog的機器,所以等於Syslog Server也不為過吧。

可能因原Indy9.x中的TIdSyslog SendMessage會和TIdMessageClient.SendMsg重名
(對IdSyslog.SendMsg做help查詢會查到TIdMessageClient.SendMsg)
所以才會在Indy10.x中改為SendLogMessage吧? (誤)