メインのメーラーの受信の邪魔をせずに、送られてくるメールのタイトル、アドレス、受信日時のみを取得するには

解決


Delphi大好き  2009-10-15 20:44:32  No: 35897

質問したい事があったので書込みしました。

Delphiで簡易メール受信探知プログラム(?)を作りたいと思っています。
が、メール関連で手元に参考になる文献が全く無く、知識も乏しく困っています。

以下の事をするプログラムを作りたいと思ってます。

バックグラウンドで実行

受信メールを探知

開封せずに、タイトルとアドレス、受信日時だけを取得
(Windows純正メーラーからメールを開けるようにする為、受信メールには一切手を加えない)

アドレスを検索して、指定した、複数の特定のアドレスのみを、
データベースにタイトル、アドレス、受信日時を記録、
チャイムを鳴らす

待機、最初に戻る

というのを作りたいと思っています

以上をする為に、参考になる文献、HP、必要なコンポーネント名等、などがあったら教えて貰えないでしょうか?
また、技術的に初心者でも可能でしょうか?
また、取得した時点で他のメーラーからの取得が出来なくなってしまわないでしょうか?

また、上記にも増してインターネット関連に疎い為、全く解らず困っています。

教えていただけると助かります。
それではよろしくお願いしますm(__)m。


Delphi大好き  2009-10-15 20:56:44  No: 35898

環境書き忘れました。

WinXP SP3  Delphi7PRO、又はTurboDelphi2006(無償版)です。


igy  2009-10-15 21:38:30  No: 35899

IndyのTIdPOP3 を使うのはいかがですか?

IdPOP3でメールチェックし送信者を知りたいがエラー
https://www.petitmonte.com/bbs/answers?question_id=6536


delphi大好き  2009-10-16 10:23:58  No: 35900

自宅にネット回線が無いので、
携帯から書いています。

igyさんありがとうございます、
まさにそれでした!
まだ作り始めですが、ある程度思い通りになりました。
indyて非常に便利なのですね。

タイトルと送信元の取得は成功したのですが、
送信日時の取得が解りません。
送信日時はメールの情報に含まれて無いのでしょうか?

明日は書き込めそうにないですが、進展があったら予定が終わり次第書き込みにきます。


igy  2009-10-16 16:35:47  No: 35901

>送信日時の取得が解りません。

TIdMessage の Date プロパティ はいかがでしょう?

# Dephi7 Proをお持ちであれば、Indy関連のヘルプも日本語で
# 記述されていますので、ヘルプを参照するのもよいかもしれません。


Delphi大好き  2009-10-16 22:37:49  No: 35902

igyさんありがとうございます、
とても助かります^^。

早速組み込んでみました。
こちらの方でも、Msg.Headers.Strings[6]を使った取得方法が判りました。

こちらのは何故か、indyのヘルプは英文でした…
正確なバージョンは、Delphi 7 Studio Professionalでした^^; 
同じDelphi7Proでも違うんですね…。

試しの試作段階ですが、以下まで出来上がりました。

後はデータベースを組んで、処理を作ってくだけです。
こんなに早くメイン部分が出来上がるとは思いませんでした^^;

それではありがとうございましたm(__)m。

procedure TForm1.Button1Click(Sender: TObject);
var
  Msg : TIdMessage;
  i : integer;
begin
  memo1.Lines.Clear;
  IdPOP31.Host    :=  'Pop3アドレス';
  IdPOP31.Port    :=  110;
  IdPOP31.Username  :=  'ユーザーネーム';
  IdPOP31.Password :=  'パスワード';
  IdPOP31.Connect;
  for i :=  1 to  IdPOP31.CheckMessages do  begin
    Msg :=  TIdMessage.Create(Self);
    IdPOP31.Retrieve(i, Msg);

    Memo1.Lines.Add(Msg.Subject{タイトル});
    Memo1.Lines.Add(Msg.From.Text{送信者});
    Memo1.Lines.Add(inttostr(IdPOP31.CheckMessages{未開封メール数}));
    Memo1.Lines.Add(Msg.Headers.Strings[6]{送信日時});
    Memo1.Lines.Add(datetostr(msg.Date{送信日}));

  end;
  IdPOP31.Disconnect;
end;


igy  2009-10-16 22:49:53  No: 35903

>こちらのは何故か、indyのヘルプは英文でした…
>正確なバージョンは、Delphi 7 Studio Professionalでした^^; 
>同じDelphi7Proでも違うんですね…。

Delphi7リリース時はIndyのヘルプは英語のものでしたが、
その後、すぐアップデートが出てた気がします。

Delphi Registered User Downloads
http://cc.embarcadero.com/reg/delphi

には、ありませんが、

ダウンロードファイル - Delphi 
http://support.codegear.com/jp/article/35932
から
  Delphi 7 - Indy ヘルプファイル・アップデート 
がダウンロードできるようです。


Delphi大好き  2009-10-17 21:30:03  No: 35904

igyさんありがとうございます、
ヘルプをインストールしたところ、きちんと日本語表示なりました。

組んでみたところ、早速問題が出ました。
上記のプログラムだと、メール取得時にメールを開いてしまうようです。

メールを開かずに題名やアドレスを、あるいは、メールを取得した後で再びメールを未読に戻す方法は無いのでしょうか?

よろしくお願いしますm(__)m。


igy  2009-10-18 06:16:46  No: 35905

>上記のプログラムだと、メール取得時にメールを開いてしまうようです。

試していませんが、
Retrieve メソッドではなく、ReceiveHeader メソッド を使った場合は、どうなりますか?


igy  2009-10-18 06:18:07  No: 35906

訂正です。

×:ReceiveHeader メソッド
○:RetrieveHeader メソッド


delphi大好き  2009-10-19 03:42:17  No: 35907

igy毎回さんありがとうございますm(__)m、
RetrieveHeaderでメールを開かずに、
タイトルと時間、アドレスを取るのに成功しました。

後はこれで何とかなりそうです。
また何かあったらよろしくお願いしますm(__)m。

それではありがとうございました。


Delphi大好き  2009-10-20 00:17:47  No: 35908

毎回ありがとうございます、
indyのメモリリークと思われるバグでつまづいたので、
先ほど、Indyを最新のIndy10に更新したのですが、
今度は以下のエラーメッセージが出るようになりました。
Delphiのバージョンは7PROです。

alreedy connected.

どのような意味のエラーなのでしょうか?

教えていただけると助かります。

それではよろしくお願いします。


読んで字のごとし  2009-10-20 02:01:31  No: 35909

接続済みなのにまた接続しようとしたとか?
これ以上は実際のソースを見られない者には答えようがない。


多分無理です  2009-10-20 05:59:59  No: 35910

基本的にSMTPポートに同時にログインできるアカウントは
一つなので(出来るサーバーもあるかもしれませんけど)
「メインのメーラーの受信の邪魔をせずに」は難しいと
思いますよ。

メインのメーラーでメール受信している間はIndyだろうと
ログイン出来ないと思います。逆もしかり。
リトライして回避が基本です。

「TELNET SMTP」で検索して見ると良いかもしれません。
RFC2821も調べてみて下さい。
メーラーもIndyもやってる事は同じです。ただのテキスト
送受信です。


Delphi大好き  2009-10-21 01:44:38  No: 35911

読んで字のごとしさん、多分無理かもさん、ありがとうございます。

メールやインターネットは殆ど判らず、思ったよりも苦戦しています。

メール受信を自動通知してくれるプロパティやメゾットがあると便利なのですが、
今は試しのプログラムですが、ほぼ上記のプログラムを無理矢理タイマーでループさせてます。

メールは、今は自分のヤフーメールで試しています。
作成したいソフトではプララのメールを予定してます。
まだプララの設定では試してないので判らないです。

以下が問題のプログラムです。
今度はFormShowでButton1を読み込んで、そこからタイマーで5秒間隔でButton2を連続実行しています。
何回か連続実行された後「invoild passwad」という、パスワードが無効ですといった感じのエラーが出ます。

やはり下のコードは無理があるのでしょうか?

procedure TForm1.Button1Click(Sender: TObject);
var
  Msg : TIdMessage;
  i : integer;
begin
  memo1.Lines.Clear;
  IdPOP31.Host    :=  'pop3アドレス';
  IdPOP31.Port    :=  110;
  IdPOP31.Username  :=  'ユーザーネーム';
  IdPOP31.Password :=  'パスワード';
  IdPOP31.Connect;

  for i :=  1 to  IdPOP31.CheckMessages do  begin
    Msg :=  TIdMessage.Create(Self);
    IdPOP31.RetrieveHeader(i, Msg);

    //数件の未開封があった場合、変数Sの値は毎回変化する
    //これでは一件しか記録できない

    //受信データ取得
    s1 := Msg.Subject{タイトル};
    s2 := Msg.From.Text{送信者};
    s3 := inttostr(IdPOP31.CheckMessages{未開封メール数});
    s4 := Msg.Headers.Strings[6]{送信日時};
    s5 := datetostr(msg.Date{送信日});

    memo1.Lines.Add(s1);
    memo1.Lines.Add(s2);
    memo1.Lines.Add(s3);
    memo1.Lines.Add(s4);
    memo1.Lines.Add(s5);
  end;
  IdPOP31.Disconnect;
  timer1.Enabled := true;

end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Msg : TIdMessage;
  i : integer;
begin
  memo1.Lines.Clear;
  IdPOP31.Connect;

  for i :=  1 to  IdPOP31.CheckMessages do  begin
    Msg :=  TIdMessage.Create(Self);
    IdPOP31.RetrieveHeader(i, Msg);

    //受信データ取得
    s1 := Msg.Subject{タイトル};
    s2 := Msg.From.Text{送信者};
    s3 := inttostr(IdPOP31.CheckMessages{未開封メール数});
    s4 := Msg.Headers.Strings[6]{送信日時};
    s5 := datetostr(msg.Date{送信日});

    memo1.Lines.Add(s1);
    memo1.Lines.Add(s2);
    memo1.Lines.Add(s3);
    memo1.Lines.Add(s4);
    memo1.Lines.Add(s5);
  end;
  IdPOP31.Disconnect;

end;

procedure TForm1.FormShow(Sender: TObject);
begin
  Button1Click(Sender);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Button2Click(Sender);
end;


Quest  2009-10-21 04:21:12  No: 35912

メールのチェック中にタイマーイベントが発生してしまうと言う事はありませんか?
(つまり、メールのチェックに5秒以上かかってしまう)
念のためタイマーイベントを
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  try
    Button2Click(Sender);
  finally
    Timer1.Enabled := True;
  end
end;
としてみてはどうでしょう。(ハズレの可能性が高いですが)


Delphi大好き  2009-10-21 18:32:51  No: 35913

Questさんありがとうございます、
早速試してみました。

何分間か実行して放置してみたのですが、無事動作しているみたいです。
何とかなりました、ありがとうございますm(__)m。
Questさんのご指摘した通りだったみたいです。

Try文はExceptしか使った事がなかったのですが、
Fainaryはこういう風に使うのですね^^。
勉強になりました^^。

データベース登録部分は殆ど完成しているので、
あとはこれを組み込むだけです。

また何かエラーがでたら(多分出ると思いますが^^;)、よろしくお願いします。

それではありがとうございましたm(__)m。


delphi大好き  2009-10-23 22:55:31  No: 35914

皆さんありがとうございます、
先程完成しました。

今の所正常動作しています。
殆どが教えて貰った事で、
自分の実力以上のものが作れました^^。
大変助かりました。
今回もありがとうございましたm(__)m。

以下が完成したコードです。

procedure TForm1.FormShow(Sender: TObject);
var
  s:string;
begin
  //変数初期化
  s1 := ''; s2 := ''; s3 := ''; s4 := ''; s5 := ''; s6 := '';
  //データベースアドレス設定
  table1.DatabaseName := ExtractFileDir( Paramstr(0) );
  Query1.DatabaseName := ExtractFileDir( Paramstr(0) );
  try
    table1.Open;
  except
    table1.CreateTable;
    table1.Open;
  end;
  Button1Click(Sender);
  caption := 'メール受信を監視しています';
  s := '';
  while 1 > 0 do begin
    if s = table1.fieldbyname('送信日時詳細').AsString then
      exit;
    ListBox1.Items.Add(table1.fieldbyname('タイトル').asstring+ '  ' +
    table1.fieldbyname('送信者').asstring + '  ' +
    table1.fieldbyname('送信日時詳細').AsString);
    s := table1.fieldbyname('送信日時詳細').AsString;
    table1.Next;
  end;
  table1.Close;
  table1.open;
   
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Msg : TIdMessage;
  i : integer;
begin  
  application.Title := 'メールチェッカー';
  listbox1.Clear;
  IdPOP31.Host    :=  'POP3アドレス';
  IdPOP31.Port    :=  110;
  IdPOP31.Username  :=  'ユーザー名';
  IdPOP31.Password :=  'パスワード';
  IdPOP31.Connect;

  //if 0 = idpop31.CheckMessages then
    //exit;
  for i :=  1 to  IdPOP31.CheckMessages do  begin
    Msg :=  TIdMessage.Create(Self);
    IdPOP31.RetrieveHeader(i, Msg);

    //受信データ取得
    s1 := Msg.Subject{タイトル};
    s2 := Msg.From.Text{送信者};
    s3 := inttostr(IdPOP31.CheckMessages{未開封メール数});
    s4 := Msg.Headers.Strings[6]{送信日時};
    s5 := datetostr(msg.Date{送信日});
 

    if s2 = 'メールアドレス1' then
      sw1 := true;
    if s2 = 'メールアドレス2' then
      sw1 := true;
    
    if SW1 then begin
          //データ検索
      Query1.SQL.Text := 'SELECT COUNT(*) FROM メールお知らせ WHERE 送信日時詳細 = "'
      + S4 + '";';
      Query1.Open;
      if 0 = Query1.fieldbyname('COUNT(*)').AsInteger then begin
        //データベース登録}
        application.Title := '受信しました';
        with table1 do begin
          Insert;
          Edit;
          FieldByName('タイトル').AsString := s1;
          FieldByName('From').AsString := s2;
          FieldByName('送信日時詳細').AsString := s4;
          FieldByName('送信日').AsString := s5;

          if s2 = 'メールアドレス1' then
            FieldByName('送信者').AsString := '1さん';
          if s2 = 'メールアドレス2' then
            FieldByName('送信者').AsString := '2さん';
          post;
          sw1 := false;
          timer2.Enabled := true;//チャイムを鳴らす
        end;
      end;
    end;
  end;
  IdPOP31.Disconnect;
  ListBox1.Items.Add(table1.fieldbyname('タイトル').asstring+ '  ' +
  table1.fieldbyname('送信者').asstring + '  ' +
  table1.fieldbyname('送信日時詳細').AsString);
  
  timer1.Enabled := true;
  form1.WindowState := wsMinimized;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Msg : TIdMessage;
  i : integer;
begin
  IdPOP31.Connect;

  for i :=  1 to  IdPOP31.CheckMessages do  begin
    Msg :=  TIdMessage.Create(Self);
    IdPOP31.RetrieveHeader(i, Msg);

    //受信データ取得
    s1 := Msg.Subject{タイトル};
    s2 := Msg.From.Text{送信者};
    s3 := inttostr(IdPOP31.CheckMessages{未開封メール数});
    s4 := Msg.Headers.Strings[6]{送信日時};
    s5 := datetostr(msg.Date{送信日});
    

   if s2 = 'メールアドレス1' then
      sw1 := true;
    if s2 = 'メールアドレス2' then
      sw1 := true;
    

    if sw1 then  
    begin
      edit1.Text := s1;
      //データ検索
      Query1.SQL.Text := 'SELECT COUNT(*) FROM メールお知らせ WHERE 送信日時詳細 = "'
      + S4 + '";';
      Query1.Open;
      if 0 = Query1.fieldbyname('COUNT(*)').AsInteger then begin
        //データベース登録}
        application.Title := '受信しました';
        with table1 do begin
          ListBox1.Items.Add(table1.fieldbyname('タイトル').asstring+ '  ' +
          table1.fieldbyname('送信者').asstring + '  ' +
          table1.fieldbyname('送信日時詳細').AsString);
          Insert;
          Edit;
          FieldByName('タイトル').AsString := s1;
          FieldByName('From').AsString := s2;
          FieldByName('送信日時詳細').AsString := s4;
          FieldByName('送信日').AsString := s5;
          if s2 = 'メールアドレス1' then
            FieldByName('送信者').AsString := '1さん';
          if s2 = 'メールアドレス2' then
            FieldByName('送信者').AsString := '2さん';

          post;
          sw1 := false;
          timer2.Enabled := true;//チャイムを鳴らす
        end;
      end;
    end;
  end;
  IdPOP31.Disconnect;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
   timer1.Enabled := false;
  try
    Button2Click(Sender);
  finally
    timer1.Enabled := true;
  end;
  i := i +1;
  caption := inttostr(i);
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
  messagebeep(mb_ok);
  if count1 = 5 then begin
    timer2.Enabled := false;
    count1 := 0;
  end;
  count1 := count1 + 1;
end;


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

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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