13

受信トレイからすべての電子メールを取得し、特定の文字列を含む電子メールをフィルタリングしてから、それらの電子メールを ArrayList に入れるアプリケーションを作成しました。

メールがリストに追加された後、そのメールの件名と内容についていくつかの作業を行っています。これは、添付ファイルのない電子メールでは問題なく機能します。しかし、添付ファイル付きの電子メールを使い始めたとき、すべてが期待どおりに機能しなくなりました。

これは私のコードです:

public void getInhoud(Message msg) throws IOException {
    try {
        cont = msg.getContent();
    } catch (MessagingException ex) {
        Logger.getLogger(ReadMailNew.class.getName()).log(Level.SEVERE, null, ex);
    }
    if (cont instanceof String) {
        String body = (String) cont;


    } else if (cont instanceof Multipart) {
        try {
            Multipart mp = (Multipart) msg.getContent();
            int mp_count = mp.getCount();
            for (int b = 0; b < 1; b++) {
                    dumpPart(mp.getBodyPart(b));
            }
        } catch (Exception ex) {
            System.out.println("Exception arise at get Content");
            ex.printStackTrace();
        }
    }
}

public void dumpPart(Part p) throws Exception {
    email = null;
    String contentType = p.getContentType();
    System.out.println("dumpPart" + contentType);
    InputStream is = p.getInputStream();
    if (!(is instanceof BufferedInputStream)) {
        is = new BufferedInputStream(is);
    }
    int c;
    final StringWriter sw = new StringWriter();
    while ((c = is.read()) != -1) {
        sw.write(c);
    }

    if (!sw.toString().contains("<div>")) {
        mpMessage = sw.toString();
        getReferentie(mpMessage);
    }
}

電子メールの内容は String に格納されます。

添付ファイルなしでメールを読もうとすると、このコードはすべて正常に機能します。しかし、添付ファイル付きの電子メールを使用すると、文字列には HTML コードと添付ファイルのコーディングも含まれます。最終的には、添付ファイルと電子メールの内容を保存したいと考えていますが、最優先事項は、HTML や添付ファイルのコーディングなしでテキストだけを取得することです。

ここで、さまざまな部分を処理するために別のアプローチを試しました。

public void getInhoud(Message msg) throws IOException {
    try {
        Object contt = msg.getContent();

        if (contt instanceof Multipart) {
            System.out.println("Met attachment");
            handleMultipart((Multipart) contt);
        } else {
            handlePart(msg);
            System.out.println("Zonder attachment");

        }
    } catch (MessagingException ex) {
        ex.printStackTrace();
    }
}

public static void handleMultipart(Multipart multipart)
        throws MessagingException, IOException {
    for (int i = 0, n = multipart.getCount(); i < n; i++) {
        handlePart(multipart.getBodyPart(i));
        System.out.println("Count "+n);
    }
}

 public static void handlePart(Part part)
        throws MessagingException, IOException {

    String disposition = part.getDisposition();
    String contentType = part.getContentType();
    if (disposition == null) { // When just body
        System.out.println("Null: " + contentType);
        // Check if plain
        if ((contentType.length() >= 10)
                && (contentType.toLowerCase().substring(
                0, 10).equals("text/plain"))) {
            part.writeTo(System.out);
        } else if ((contentType.length() >= 9)
                && (contentType.toLowerCase().substring(
                0, 9).equals("text/html"))) {
            part.writeTo(System.out);
        } else if ((contentType.length() >= 9)
                && (contentType.toLowerCase().substring(
                0, 9).equals("text/html"))) {
            System.out.println("Ook html gevonden");
            part.writeTo(System.out);
        }else{
            System.out.println("Other body: " + contentType);
            part.writeTo(System.out);
        }
    } else if (disposition.equalsIgnoreCase(Part.ATTACHMENT)) {
        System.out.println("Attachment: " + part.getFileName()
                + " : " + contentType);
    } else if (disposition.equalsIgnoreCase(Part.INLINE)) {
        System.out.println("Inline: "
                + part.getFileName()
                + " : " + contentType);
    } else {
        System.out.println("Other: " + disposition);
    }
}

これは、System.out.printlns

Null: multipart/alternative; boundary=047d7b6220720b499504ce3786d7
Other body: multipart/alternative; boundary=047d7b6220720b499504ce3786d7
Content-Type: multipart/alternative; boundary="047d7b6220720b499504ce3786d7"

--047d7b6220720b499504ce3786d7
Content-Type: text/plain; charset="ISO-8859-1"

'Text of the message here in normal text'

--047d7b6220720b499504ce3786d7
Content-Type: text/html; charset="ISO-8859-1"
Content-Transfer-Encoding: quoted-printable

'HTML code of the message'

この方法では、電子メールの通常のテキストだけでなく、メールの HTML コーディングも返されます。なぜこれが起こるのか本当にわかりません。グーグルで検索しましたが、この問題を抱えている人は他にないようです。

どんな助けでも大歓迎です、

ありがとう!

4

3 に答える 3

27

JavaMail ライブラリを使用して電子メールを読むのは、予想以上に難しいことがわかりました。私は JavaMail API を責めるのではなく、インターネット電子メールの公式定義であるRFC-5322に対する私の理解不足を責めます。

思考実験として: 電子メール メッセージが現実世界でどれほど複雑になるかを考えてみましょう。メッセージ内にメッセージを「無限に」埋め込むことができます。各メッセージ自体には、複数の添付ファイル (バイナリまたは人間が判読できるテキスト) が含まれる場合があります。解析後、JavaMail API でこの構造がどれほど複雑になるか想像してみてください。

JavaMail で電子メールをトラバースする際に役立ついくつかのヒント:

  • Message両方ともBodyPart実装しPartます。
  • MimeMessage両方ともMimeBodyPart実装しMimePartます。
  • 可能であれば、すべてをPartまたはとして扱いますMimePart。これにより、一般的なトラバーサル メソッドをより簡単に構築できるようになります。

これらのPartメソッドはトラバースに役立ちます:

  • String getContentType(): MIME タイプで始まります。これを MIME タイプとして扱いたくなるかもしれませんが (多少のハッキング/カット/マッチングを行います)、そうしないでください。このメソッドは、検査のためにデバッガー内でのみ使用することをお勧めします。
    • 奇妙なことに、MIME タイプを直接抽出することはできません。代わりに使用boolean isMimeType(String)して一致させます。などの強力なワイルドカードについては、ドキュメントをよく読んでください"multipart/*"
  • Object getContent(): かもしれませんinstanceof:
    • MultipartPart-- より多くの s の コンテナ
      • にキャストし、とMultipartを使用してゼロから始まるインデックスとして反復するint getCount()BodyPart getBodyPart(int)
        • 注:BodyPart実装しますPart
      • 私の経験では、Microsoft Exchange サーバーは、プレーン テキストと HTML の 2 つの本文テキストを定期的に提供しています。
        • プレーンテキストと一致させるには、次を試してください。Part.isMimeType("text/plain")
        • HTML に一致させるには、次を試してください。Part.isMimeType("text/html")
    • Message(implements Part) -- 埋め込まれた、または添付された電子メール
    • String(本文のみ -- プレーンテキストまたは HTML)
      • 上記の Microsoft Exchange サーバーに関する注記を参照してください。
    • InputStream(おそらく BASE64 でエンコードされた添付ファイル)
  • String getDisposition(): 可能性のある値null
    • の場合Part.ATTACHMENT.equalsIgnoreCase(getDisposition())、呼び出しgetInputStream()て添付ファイルの raw バイトを取得します。

最後に、公式の Javadoccom.sun.mailがパッケージ内のすべて (およびおそらくそれ以上) を除外していることがわかりました。これらが必要な場合は、コードを直接読むか、ソースをダウンロードしてプロジェクトのプロジェクト モジュールで実行mvn javadoc:javadocすることにより、フィルタリングされていない Javadoc を生成します。mail

于 2013-06-05T04:51:11.867 に答える
1

Kevin の有益なアドバイスに従って、メール コンテンツの Java オブジェクト タイプを正規名 (または単純な名前) に関して分析することも役立ちます。たとえば、私が今持っている 1 つの受信トレイを見ると、486 件のメッセージのうち 399 件が文字列で、87 件が MimeMultipart です。これは、私の典型的な電子メールの場合、最初に文字列を剥がすためにinstanceofを使用する戦略が最適であることを示唆しています。

文字列のうち、394 が text/plain で、5 が text/html です。これはほとんどの場合当てはまりません。これは、この特定の受信トレイへの私のメール フィードを反映しています。

しかし、待ってください - まだまだあります!!! :-) それにもかかわらず、HTML はそこに忍び込みます: 87 のマルチパートのうち、70 はマルチパート/代替です。保証はありませんが、ほとんど (すべてではないにしても) は TEXT + HTML です。

他の 17 個のマルチパートのうち、15 個がマルチパート/混合で、2 個がマルチパート/署名済みです。

この受信トレイ (および他の 1 つ) の使用例は、主に既知のメーリング リスト コンテンツを集約して分析することです。メッセージを無視することはできませんが、この種の分析は、処理をより効率的にするのに役立ちます。

于 2014-05-17T15:29:02.893 に答える