XE2標準搭載のIndy10で添付ファイルを保存するには?

解決


RAD命  2012-02-01 22:58:50  No: 41522

先ほどのIndyの文字化けの件は大変ありがとうございました。

WinXP、C++BuilderXE2スターターです。

山本隆の開発日誌さんの、
C++Builder2010とIndy10でメールを送信する
http://www.gesource.jp/programming/bcb/97.html
と、

Mr.XRAYさんの、
776_TIdPOP3を使用してメール受信
http://mrxray.on.coocan.jp/Delphi/plSamples/776_IdPOP3MailClient.htm

を参考にしながら書いています。

添付ファイルを参照することまでは出来たのですが、
添付ファイルを保存する所までが辿りつけません。
色々試行錯誤してみたのですが、Header情報を保存してしまうのみで、
添付ファイルを保存できません。

こちらの環境には、TIdAttachmentFileコンポーネントが無いようで、検索でも余り情報が引っかからず、お手上げ状態です。

IndyをTIdAttachmentFileがある、古いバージョンにしてしまう事も考えてます。

どなたか、お知恵を拝借いただけると助かりますm(__)m。

以下ソースです。

//テスト受信
bool result = IdPOP31->Retrieve(5049, msg); //メールの番号は1から
if (result)
{
  StringGrid1->Cells[1][1] = msg->Subject;
  StringGrid1->Cells[2][1] = msg->Body->Text;
  StringGrid1->Cells[3][1] = msg->Date;
  StringGrid1->Cells[4][1] = msg->From->Text;
  StringGrid1->Cells[5][1] = item->Address;
  StringGrid1->Cells[6][1] = msg->Headers->Text;
  int i = 1;

  while ("" != msg->MessageParts->Items[i]->FileName)
  {
   try
   {
    StringGrid1->Cells[7][1] = StringGrid1->Cells[7][1] + msg->MessageParts->Items[i]->FileName;
          //↓ここが問題の部分です。
    msg->SaveToFile("d:\\aaa.txt",msg->MessageParts->Items[i]->Headers);
   }
    catch  (int)
    {

    }
  }

   }
else
{
  MessageDlg("メールの受信に失敗しました。", mtError, TMsgDlgButtons() << mbOK, 0);
}
}


Mr.XRAY  2012-02-02 00:14:51  No: 41523

こんにちは.Mr.XRAYです.

>IndyをTIdAttachmentFileがある、古いバージョンにしてしまう事も考えてます。

古いバージョンにあるかどうかは知りませんが,Indyのインストール先にIdAttachmentFileという名前の
ファイルが,もしあったら,usseに追加して見てください.
ない場合は,分かりません.


Mr.XRAY  2012-02-02 00:18:30  No: 41524

ゴメンなさい.C++だから  #include ですね.


RAD命  2012-02-02 04:14:48  No: 41525

Mr.XRAYさんありがとうございます。
探してみたところ、そのファイルはCBuilderXE2に入っていました。

しかし、今度は「system.Classes.pas」というファイルが必要だと、
コンパイラから怒られました。
そこでそのファイルを探してみたのですが、PC上にありませんでした。
コードの書き方が間違っているのでしょうか?

以下がサイトを参考にしながら書いてみたコードです。

void __fastcall TForm1::Button3Click(TObject *Sender)
{
//メールを受信する
UnicodeString AFileName = "d:\\aaa.txt";
TIdMessage* msg = new TIdMessage(NULL);
TIdEMailAddressItem* item = msg->Recipients->Add();
TIdAttachmentFile* attached = new TIdAttachmentFile(
  msg->MessageParts,
  msg->MessageParts->Items[1]->FileName); //ファイルのパス

bool result = IdPOP31->Retrieve(5049, msg); //メールの番号は1から
if (result)
{
  StringGrid1->Cells[1][1] = msg->Subject;
  StringGrid1->Cells[2][1] = msg->Body->Text;
  StringGrid1->Cells[3][1] = msg->Date;
  StringGrid1->Cells[4][1] = msg->From->Text;
  StringGrid1->Cells[5][1] = item->Address;
  StringGrid1->Cells[6][1] = msg->Headers->Text;
  int i = 1;

  while ("" != msg->MessageParts->Items[i]->FileName)
  {
   try
   {
    StringGrid1->Cells[7][1] = StringGrid1->Cells[7][1] + msg->MessageParts->Items[i]->FileName;
          //↓この部分が自分が書いた部分で、最も怪しい部分です。
    attached->SaveToFile(AFileName);

   }
    catch  (int)
    {

    }
  }

   }
else
{
  MessageDlg("メールの受信に失敗しました。", mtError, TMsgDlgButtons() << mbOK, 0);
}
}


RAD命  2012-02-02 05:38:38  No: 41526

コードを整理したところ、初歩的バグが多数あったので、
直しましたが、まだダウンロードに失敗します。
少しずつ原因が見えてきて、自分の技量不足が、
最大の要因っぽいです。

以下、現在のコードです。
どなたかお知恵をお貸しいただけると助かりますm(__)m。

void __fastcall TForm1::Button3Click(TObject *Sender)
{
//メールを受信する
TIdMessage* msg = new TIdMessage(NULL);
TIdEMailAddressItem* item = msg->Recipients->Add();

//1件だけ試し受信
bool result = IdPOP31->Retrieve(5049, msg); //メールの番号は1から
if (result)
{
  StringGrid1->Cells[1][1] = msg->Subject;
  StringGrid1->Cells[2][1] = msg->Body->Text;
  StringGrid1->Cells[3][1] = msg->Date;
  StringGrid1->Cells[4][1] = msg->From->Text;
  StringGrid1->Cells[5][1] = item->Address;
  StringGrid1->Cells[6][1] = msg->Headers->Text;
  int i = 1;

  while ("" != msg->MessageParts->Items[i]->FileName)
  {
    try
    {
     TIdAttachmentFile* attached = new TIdAttachmentFile(
     msg->MessageParts,
     msg->MessageParts->Items[i]->FileName); //ファイルのパス
     StringGrid1->Cells[7][1] = StringGrid1->Cells[7][1] + msg->MessageParts->Items[i]->FileName;
     attached->SaveToFile("d:\\" + msg->MessageParts->Items[i]->FileName);
    }
    catch  (int)
    {

    }
    i += 1;
  }
   }
else
{
  MessageDlg("メールの受信に失敗しました。", mtError, TMsgDlgButtons() << mbOK, 0);
}
}


Mr.XRAY  2012-02-02 06:17:43  No: 41527

コードを見せられても....

>しかし、今度は「system.Classes.pas」というファイルが必要だと、

ではなかったんでしたっけ.

Delphiの場合ですが,新規でVCLフォームアプリケーションを作句すると.usesが

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
  
となります.新規のユニット作成の場合は何もありません.
Delphiでは,これらのファイルの拡張子は.pas(パスカルのパス)です.

このファイルにいろいろなクラスやメソッド,関数類が書いてあり,それらを使用するするわけです.
コンポーネントをフォームに配置した時は,自動で,必要なものが追加されます.
そうでない場合は,今回のように,自分が追加することになります.
おそらく,C++BuilderXE2 も同様に #include があるのではないかと思われます.

この中で,System.Classes  にはかなり基本的なコード類が収めてあります.  
もし,これがないとすると,相当値切って購入したか,その C++BuilderXE2 のファイル構成やら,
何かの設定が壊れているではないかと思います.

一度,新規のプロジェクトを作成して,その動作を確認してみてはいかがでしょうか.
残念ですが,私には,これ以上のことは分かりません.


山本隆  2012-02-02 10:15:54  No: 41528

C++Builder XEで添付ファイルを保存するソースコードです。
参考になれば。

for (int i = 0; i < IdMessage1->MessageParts->Count; ++i)
{
  TIdMessagePart* part = IdMessage1->MessageParts->Items[i];
  if (part->PartType() == mptAttachment)
  {
    TIdAttachmentFile* attached = dynamic_cast<TIdAttachmentFile*>(part);
    if (attached != 0)
    {
      //TODO:ファイル名はデコードする必要がある
      attached->SaveToFile(attached->FileName);
    }
  }
}


RAD命  2012-02-03 19:32:33  No: 41529

>Mr.XRAYさん
    ご指摘ありがとうございます、原因のひとつが判りました。
    プロジェクトファイルが壊れていました(笑)。
    それに気づかず、Builderを3回ほどクリーンインストールしてしまいました・・・。
    Indy10を無理やり古いバージョンと交換したところ、BuilderのIndyが再インストール不能となり、
    またインストール、それでもIndyが正常に認識されず、駄目元でプロジェクトを新規作成してみたら、
    あっさりと動きました^^;。
    system.Classesというのは、Builderのプロジェクトファイルの一番先頭に記述されていて、
    Indy10使用時にエラーを起こすと、そのメッセージが出るみたいです。
    バグをつぶしていったところ、そのエラーは出なくなりました。
    お騒がせしました^^;。

>山本隆さん
ありがとうございます!!m(__)m
サイト参考にさせてもらっています。
DelphiからC++Builderに移ってまだ日が浅いので、大変参考になります。

早速実装したところ、きれいに動きました(!)
C++で組むのを諦めて、Delphiで組みなおしている最中でした。

助かりました、皆さん本当にありがとうございますm(__)m。

以下、完成したメール読み込み部です。

折角Delphiでも作ったので、(自身の勉強の為にも)後ほどDelphiで組んだものも載せておきます。

環境
WinXP  C++BuilderXE2スターター
メール読み込み部分

void __fastcall TForm1::Button3Click(TObject *Sender)
{
chekcount = IdPOP31->CheckMessages();
Button5Click(Sender);

//メールを受信する
TIdMessage* msg = new TIdMessage(NULL);
TIdEMailAddressItem* item = msg->Recipients->Add();
//int i1 = 1;
//1件だけ試し受信
int mailcount = 1;
int message = 2;//IdPOP31->CheckMessages();
StringGrid1->RowCount = IdPOP31->CheckMessages();
  while (message > mailcount)
{
bool result = IdPOP31->Retrieve(5049, msg); //メールの番号は1から
if (result)
{
  StringGrid1->Cells[1][mailcount] = msg->Subject;
  StringGrid1->Cells[2][mailcount] = msg->Body->Text;
  StringGrid1->Cells[3][mailcount] = msg->Date;
  StringGrid1->Cells[4][mailcount] = msg->From->Text;
  int Ritems = 0;
  int Rcount = msg->Recipients->Count;
  while ( Ritems  <  Rcount + 1)
  {
  StringGrid1->Cells[5][mailcount] = StringGrid1->Cells[5][mailcount] + msg->Recipients->Items[Ritems]->Text + char(13);
  Ritems += 1;
  if (Ritems == Rcount)
  {
    Ritems += 2;
  }

  }
  StringGrid1->Cells[6][mailcount] = msg->Headers->Text;

  for (int i = 0; i < msg->MessageParts->Count; ++i)
{
  TIdMessagePart* part = msg->MessageParts->Items[i];
  if (part->PartType() == mptAttachment)
  {
  TIdAttachmentFile* attached = dynamic_cast<TIdAttachmentFile*>(part);
  if (attached != 0)
  {
    //TODO:ファイル名はデコードする必要がある
    StringGrid1->Cells[7][mailcount] = StringGrid1->Cells[7][mailcount] + attached->FileName;
    attached->SaveToFile("d:\\" + attached->FileName);
  }
  }
}


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

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






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