TIdMessageのOnInitializeISOイベント割り当て


ぐーすか  2019-10-10 13:03:56  No: 148288

Indyでメールを送信する自作関数を作成しようと思っています
下記のURLを参考に作成しているのですが、
TIdMessageのOnInitializeISOイベントの割り当て方法が分からなくて悩んでいます
https://ht-deko.com/tech040.html#tech085

ちなみにメール送信関数は1つのユニットに記述しており、
TIdMessageコンポーネントも関数内部で動的にCreateしています
他のアプリからそのユニットをusesする形で再利用することを考えています
上記のURLでの例のようにフォーム上にTIdMessageコンポーネントが配置できれば
いいのですが・・・

// メール送信関数
function ComSendMailWithCC(Host, Subject, Name, From, Mailto, Text: String; Cc: String = ''): Boolean;
const
//*=== メール設定情報 ===*/
  MAIL_CHARSET     = 'UTF-8';      // 文字コード
  MAIL_CONTENTTYPE = 'text/plain'; // コンテンツ種別
  MAIL_ENCODING    = 'BASE64';     // エンコーディング
var
  smtp: TIdSMTP;
  msg : TIdMessage;
begin
//*** 復帰値の初期値を設定する ***/
  Result := True;    // 正常終了

//*** 変数を初期化する ***/
  smtp := nil;
  msg  := nil;

//*** メールを送信する ***/
  try
  try
    //*=== SMTPサーバの接続 ===*/
    smtp := TIdSMTP.Create(nil);
    smtp.Host := Host;
    smtp.Connect;

    //*=== メッセージオブジェクトの作成 ===*/
    msg := TIdMessage.Create(smtp);
    msg.OnInitializeISO := ;      // ←??? 
    msg.ContentType               := MAIL_CONTENTTYPE;
    msg.CharSet                   := MAIL_CHARSET;
    msg.ContentTransferEncoding   := MAIL_ENCODING;
    msg.Subject                   := Subject;
    msg.From.Name                 := Name;
    msg.From.Address              := From;
    msg.Recipients.EMailAddresses := Mailto;
    msg.CCList.EMailAddresses     := Cc;
    msg.Body.Text                 := Text;

    //*=== メール送信 ===*/
    smtp.Send(msg);
  except
    Result := False;    // 異常終了
  end;
  finally
    //*=== メッセージオブジェクトの破棄 ===*/
    if msg <> nil then msg.Free;

    //*=== SMTPサーバの切断 ===*/
    if smtp <> nil then
    begin
      smtp.Disconnect;
      smtp.Free;
    end;
  end;
end;


ぐーすか  2019-10-10 14:01:04  No: 148289

自己レスです
下記のようなやり方でとりあえずイベントは動いたようです
ネット上の色々なサイトのコードを参考にして継ぎはぎしたコードなので全く自信がありません

type
  TIdMessage1 = class(TIdMessage)
  private
    FOnInitializeISO: TIdInitializeISOEvent;
  public
    procedure DoInitializeISO(var VHeaderEncoding: Char; var VCharSet: String); override;
  published
    property OnInitializeISO: TIdInitializeISOEvent read FOnInitializeISO write FOnInitializeISO;
end;

procedure TIdMessage1.DoInitializeISO(var VHeaderEncoding: Char; var VCharSet: String);
begin
  inherited;
  if Assigned(FOnInitializeISO) then
  begin
    VHeaderEncoding := 'B';
    VCharSet := 'UTF-8';
  end;
end;

function ComSendMailWithCC(Host, Subject, Name, From, Mailto, Text: String; Cc: String = ''): Boolean;
const
//*=== メール設定情報 ===*/
  MAIL_CHARSET     = 'UTF-8';      // 文字コード
  MAIL_CONTENTTYPE = 'text/plain'; // コンテンツ種別
  MAIL_ENCODING    = 'BASE64';     // エンコーディング
var
  smtp: TIdSMTP;
  msg : TIdMessage1;
begin
//*** 復帰値の初期値を設定する ***/
  Result := True;    // 正常終了

//*** 変数を初期化する ***/
  smtp := nil;
  msg  := nil;

//*** メールを送信する ***/
  try
  try
    //*=== SMTPサーバの接続 ===*/
    smtp := TIdSMTP.Create(nil);
    smtp.Host := Host;
    smtp.Connect;

    //*=== メッセージオブジェクトの作成 ===*/
    msg := TIdMessage1.Create(smtp);
    msg.ContentType               := MAIL_CONTENTTYPE;
    msg.CharSet                   := MAIL_CHARSET;
    msg.ContentTransferEncoding   := MAIL_ENCODING;
    msg.Subject                   := Subject;
    msg.From.Name                 := Name;
    msg.From.Address              := From;
    msg.Recipients.EMailAddresses := Mailto;
    msg.CCList.EMailAddresses     := Cc;
    msg.Body.Text                 := Text;

    //*=== メール送信 ===*/
    smtp.Send(msg);
  except
    Result := False;    // 異常終了
  end;
  finally
    //*=== メッセージオブジェクトの破棄 ===*/
    if msg <> nil then msg.Free;

    //*=== SMTPサーバの切断 ===*/
    if smtp <> nil then
    begin
      smtp.Disconnect;
      smtp.Free;
    end;
  end;
end;


take  2019-10-15 08:50:40  No: 148293

プログラム自体に問題は無さそうですがプログラムの記述にいくつか疑問が残ります。

  smtp := nil;
  try
    smtp := TIdSMTP.Create(nil);
  finally
    if smtp <> nil then
    begin
      smtp.Disconnect;
      smtp.Free;
    end;
  end;

となっていますが
クラスの生成と try の関係は

  smtp := TIdSMTP.Create(nil);
  try
  finally
    smtp.Free;
  end;

このように記述すべきで
そのように書いていないので代入文やifが増えていってますね。
元の書き方だとクラス生成前にエラーになると finallyに飛んで 
freeでエラーになるので free前にわざわざ生成されたか判断しているかと

Connectで接続先が見つからなくてもそのまま処理が進むのが不安です。

あとエラーにはなりませんが、
Connectされる前にエラーでfinallyに飛ぶとDisconnectされるみたいですね。


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加