メールの受信一覧をクリックすると,メール本文が表示されるようにしているのですが,いつも実行時にエラーが出ます。「List index out of bounds」や「Access violation at adress・・・ 」など出ます。一番古い2通のメールは表示されるのですが、3通目から本文が表示されません。
これは何なんでしょうか?
コードはこちらです。
procedure TForm1.btnReceptionClick(Sender: TObject);
var
i: integer;
a,b,s: string;
begin
begin
IdPOP31.Connect;
a := ' 送信者:';
b := ' 件名:';
//メールの送信者,送信日,件名,本文を表示する
for i := 1 to IdPOP31.CheckMessages do begin
SetLength(Main,IdPOP31.CheckMessages);
Msg := TIdMessage.Create(Self);
IdPOP31.Retrieve(i, Msg);
ListBox1.Items.Add(datetostr(msg.Date)+ a + Msg.From.Text + b + Msg.Subject);
if(Msg.MessageParts.Items[0] is TIdText)then
s := TIdText(Msg.MessageParts.Items[0]).Body.Text;
Main[i] := jconvert.ConvertJCode(s, SJIS_OUT);
end;
end;
IdPOP31.Disconnect;
end;
>これは何なんでしょうか?
なんでしょうね?
Mainとは?
受信メールは何通?
ループの中でTIdMessageを何度もCreateしない方がいい。破棄もしてないようだし。
SetLengthしているところから、Mainは何かの動的配列だと推測されますが…
動的配列の場合、長さしか指定できないので、添字は必ず0から始まります。
下限が0で個数がNだったら、添字の範囲は 0 から N-1 までです。
例えばIdPOP31.CheckMessagesの値が3とした場合、長さが3に設定されるので、利用できる配列の要素は
Main[0], Main[1], Main[2]
の3つです。それに対してforループは1から始めていますから
Main[1], Main[2], Main[3]
となって、用意した領域をはみ出してしまいますね。
範囲エラーだとメッセージが出ているので、まずはこういった添字の指定が合っているかチェックしてみてはどうでしょうか。
ついでに、SetLengthは1回だけやればいいので、ループの中に入れる必要はないと思います。
Mr.XRAYです.
酒が入って,途中で寝て,今目が醒めてしまいましたので,ちょっとやってみました.
まず,苦言を.提示してあるコードおかしいです.
そんなに長いコードではないと思いますので,キチンと掲載しましょうね.
そこで,勝手にこんなことがしたいと想像(創造かもしれない?)したものです.
新規フォームにIdPOP3,Button,istbox,RichEditを配置して以下のコードをコピペしてください.
また,環境の記載がないので,動作確認は以下です.
他のバージョンでは,文字コードのコンバートが必要かも知れません.
(TPanelとTSplitterを使用していますが,体裁のためです.無視してOKです)
Windows XP(SP3) + Delphi2010(UP5) Pro + Indey 10.5.5
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
IdExplicitTLSClientServerBase, IdMessageClient, IdPOP3, StdCtrls, ComCtrls,
ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
ListBox1: TListBox;
Splitter1: TSplitter;
RichEdit1: TRichEdit;
Button1: TButton;
IdPOP31: TIdPOP3;
procedure Button1Click(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses IdMessage, IdText;
{$R *.dfm}
//=============================================================================
// 使用したオブジェクトは必ず破棄
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
i:integer;
begin
for i := 0 to ListBox1.Items.Count-1 do
Dispose(PString(ListBox1.Items.Objects[i]));
end;
//=============================================================================
// 受信
// 受信したらListBoxのItemのCaptionに送信者等の文字列を代入
// ListBoxのItem番号と対応のあるメール本文を表示させるために,ItemのDataオブ
// ジェクトに本文を代入しておく
// 配列などを用いて,その配列要素番号とListBoxのItem番号の対応でメール本文を
// 取出してもよい
// この方が動作は軽くなるが,このサンプルではテキスト部分だけを扱っているので,
// 目に見える差はないだろう
//
// このサンプルコードでは,添付ファイルの処理は行っていない
//
// TIdMessaegの使用にはusesにIdMessageが必要
// TIdTextの使用にはusesにIdTextが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
//ListViewのItemのDataプロパティに追加する文字オブジェクト生成
function NewStr(S: string): PString;
begin
New(Result);
Result^ := S;
end;
//---------------------------------------------------------------------------
var
i : Integer;
k : Integer;
a : string;
b : string;
s : string;
Msg : TIdMessage;
ACaption : string;
begin
//Dataオブジェクトがあったら破棄
for i := 0 to ListBox1.Items.Count-1 do
Dispose(PString(ListBox1.Items.Objects[i]));
//アカウント類の設定
IdPOP31.Host := 'pop.nifty.ne.jp';
IdPOP31.Username := 'HGH03072';
IdPOP31.Password := '98HGXON';
//固定値なので最初の方で設定
a := ' 送信者:';
b := ' 件名:';
IdPOP31.Connect;
//クリアしないと同じメールを何度でも表示することになる
ListBox1.Items.Clear;
Msg := TIdMessage.Create(Self);
//受信開始
for i := 1 to IdPOP31.CheckMessages do
begin
IdPOP31.Retrieve(i, Msg);
ACaption := datetostr(msg.Date)+ a + Msg.From.Text + b + Msg.Subject;
if Msg.MessageParts.Count > 0 then
begin
for k := 0 to MSG.MessageParts.Count -1 do
begin
//HTMLメールのHTML部分または添付のHTMLメールのHTMLテキスト
if Msg.MessageParts[k].ContentType = 'text/html' then
begin
s := TIdText(Msg.MessageParts[k]).Body.Text;
ListBox1.AddItem(ACaption, TObject(NewStr(s)));
end else
//HTMLメールののplainテキスト部分
if Msg.MessageParts[k].ContentType = 'text/plain' then
begin
s := TIdText(Msg.MessageParts[k]).Body.Text;
ListBox1.AddItem(ACaption, TObject(NewStr(s)));
end else
begin
//添付ファイル類なので取得しても表示不可
end;
end;
end else
begin
//plainテキスト形式のメール本文
s := Msg.Body.Text;
ListBox1.AddItem(ACaption, TObject(NewStr(s)));
end;
end;
IdPOP31.Disconnect;
end;
//=============================================================================
// ListBoxのItemをクリックしたらDataプロパティからテキストを取出して表示
//=============================================================================
procedure TForm1.ListBox1Click(Sender: TObject);
var
AIndex : Integer;
S : string;
begin
AIndex := ListBox1.ItemIndex;
if AIndex < 0 then exit;
RichEdit1.Clear;
if ListBox1.Items.Objects[AIndex] <> nil then
begin
s := PString(ListBox1.Items.Objects[AIndex])^;
RichEdit1.Text := s;
end;
end;
end.
また眠くなってきましたので,詳しい説明は省略します.
コード内のコメントでご容赦ください.
メールの知識も必要となるでしょう.
初心者には難解となるかも知れませんが,他のサンプルもあります.
http://mrxray.on.coocan.jp/Delphi/plSamples/776_IdPOP3MailClient.htm
ツイート | ![]() |