メーラー作りましょ(1) | 今宵は月が高い。注意されたし。

メーラー作りましょ(1)

ゴーストに乗っけてやろう、というつもりなんですが、とりあえず試作しています。

そうはいっても IdPOP3 べったりですけどね…… ただ IdPOP3 の取得したメールは subject が上手く読めないわけですよ。複数行が読めない。
てなわけで、RetrieveRaw で TStrings に突っ込んでおいて、ヘッダから取り出した情報を一行ずつ変換。あー面倒。

変換には JConvert 使いました。って言うか実質は何もしてない飢餓……JConvert で処理すると、何故か文末に ESC(J が付随するのでそれは削除させています。これで ISO-2022-JP デコードは完璧。

だけどヘッダの UTF-8 のデコードは上手くいきませぬ、一体どうやったらいいのやら。Delphi の UTF 関数はここでは役に立ちまへんヽ(`Д´)ノ


var
  Msg: TStringList;
  Cnt: integer;
  I : integer;
  Wrk: String;
begin
  IdPOP3.Connect;

  Cnt := IdPOP3.CheckMessages;
  for I:=1 to Cnt do begin
    Msg := TStringList.Create;
    if IdPOP3.RetrieveRaw( I, Msg ) then
    begin
      Wrk := GetMailSubject( Msg.Text );
      FMsgList.AddObject( Wrk, Msg )
    end else begin
      Wrk := 'miss of '+IntToStr(I);
      FMsgList.Add( Wrk );
    end;
    
    ListBox1.Items.Add( Wrk );
    StatusBar1.SimpleText := Format( 'read %d of %d ..."%s"', [I,Cnt, Wrk] );

    Application.ProcessMessages;
  end;
    
  IdPOP3.Disconnect;
end;


procedure TForm1.ListBox1Click(Sender: TObject);
var
  Idx: Integer;
  SL : TStrings;
begin
  Editor.Clear;

  Idx := ListBox1.ItemIndex;
  if (Idx = -1) then Exit;

  SL := TStrings(FMsgList.Objects[Idx]);
  Editor.Lines.Text := jconvert.ConvertJCode( SL.Text, SJIS_OUT );
end;


function TForm1.GetMailSubject( Msg:String ): String;
function ConvertShiftJis( Str:String ): String;
begin
  try
    Str := AnsiReplaceText( Str, '===?=', '=?=' );
    Result := jconvert.jis2sjis( jconvert.DecodeHeaderString( Str ) );
  except
    Result := Str;

  end;
end;
function ConvertUTF8( Str:String ): String;
type
  TFunc = function( const A,B: String ): Boolean;
  function TrimEx( F:TFunc; const SubStr:String; var AText:String ): String;
  begin
    if F(SubStr,AText) then Delete( AText,AnsiPos(UpperCase(SubStr),UpperCase(AText)), Length(SubStr) );
  end;
begin
  Str := Trim( Str );
  TrimEx( AnsiStartsText, '=?utf-8?q?', Str );
  TrimEx( AnsiEndsText, '?=', Str );
  Result := Str;
end;
var
  SL : TStringList;
  Idx: Integer;
  I : Integer;
  Wrk: String;
  UPC: String;
  Tmp: Char;
begin
  SL := THashedStringList.Create;
  try
    SL.Text := Msg;
    Idx := SL.IndexOf('');
    for I:=Idx to SL.Count-1 do SL.Delete( Idx );

    Idx := -1;
    for I:=0 to SL.Count-1 do
    begin
      if (Idx = -1) then Idx := IfThen( AnsiStartsText( 'subject:', SL[I] ), I, -1 );
      SL[I] := StringReplace( SL[I], ':', '=', [] );
    end;

    if (Idx > -1) then
    begin
      Result := '';
      Wrk := SL.Values['subject'];

      repeat
        UPC := UpperCase( Wrk );
        if AnsiPos( '=?ISO-2022-JP?B?', UPC )>0 then Wrk := ConvertShiftJis( Wrk )
        else if AnsiPos( '=?UTF-8?Q?', UPC )>0 then Wrk := ConvertUTF8( Wrk );
        
        if AnsiEndsText( #$1B+'(j', Wrk ) then Delete( Wrk, Length(Wrk)-2, 3 );

        Result := Result +Wrk;
        Inc(Idx);
        Wrk := SL[Idx];
        if (Wrk <> '') then Tmp := Wrk[1] else Tmp := #0;
        if (Tmp in [#9,' ']) then Delete( Wrk, 1, 1 );
      until not (Tmp in [#9,' ']) or (Idx = SL.Count-1);
    
    end else
      Result := ConvertShiftJis( SL.Values['subject'] );

  finally
    SL.Free;
  end;
end;