在android

时间:2018-04-27 17:47:33

标签: java android email javamail

我正在构建一个Android电子邮件客户端应用。我设法在RecylerView中显示电子邮件标题/发件人。接下来,我想开始一个新活动,当用户选择特定邮件时,该活动将显示电子邮件内容/附件。

我很难通过意图来做到这一点。我能够获取电子邮件的内容(文本,内嵌图像,附件),但我无法找到一种尽可能接近原始格式的方式。我想将文本放在StringBuilder中并通过意图发送它以显示文本,但这样我就无法在正确的位置显示内嵌图像,并且还存在格式问题。

对我应该采用的方式提出任何形式的指导都非常感激。

显示可用邮件列表并获取特定邮件内容的类,以便向其发送另一个用于显示邮件的活动。我知道代码有点危险,我尝试了很多方法,它远非最终形式。

public class CheckMail extends Activity {


static List<Message> messages = new ArrayList<>();
String[] sender;
String[] date;
String[] subject;
boolean[] seen;
Context context = null;
ListView listView;
Intent intent;
Store store;
StringBuilder content = new StringBuilder();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_check_mail);
    if (android.os.Build.VERSION.SDK_INT > 9)
    {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }

    context = this;


    ReadEmails task = new ReadEmails();
    task.execute();

}

public void writePart(Part p) throws Exception {
    if (p instanceof Message)
        this.writeEnvelope((Message) p);



    //check if the content is plain text
    if (p.isMimeType("text/plain")) {

      content.append(p.getContent().toString());


    }

    //check if the content has attachment
    else if (p.isMimeType("multipart/*")) {
        System.out.println("This is a Multipart");
        System.out.println("---------------------------");
        Multipart mp = (Multipart) p.getContent();
        int count = mp.getCount();
        for (int i = 0; i < count; i++)
            writePart(mp.getBodyPart(i));
    }

     //check if the content is a nested message
    else if (p.isMimeType("message/rfc822")) {
        System.out.println("This is a Nested Message");
        System.out.println("---------------------------");
        writePart((Part) p.getContent());
    }


    /*
    //check if the content is an inline image
    else if (p.isMimeType("image/jpeg")) {
        System.out.println("--------> image/jpeg");
        Object o = p.getContent();

        InputStream x = (InputStream) o;
        // Construct the required byte array
        System.out.println("x.length = " + x.available());
        while ((i = (int) ((InputStream) x).available()) > 0) {
            int result = (int) (((InputStream) x).read(bArray));
            if (result == -1)
                int i = 0;
            byte[] bArray = new byte[x.available()];

            break;
        }
        FileOutputStream f2 = new FileOutputStream("/tmp/image.jpg");
        f2.write(bArray);
    }
    else if (p.getContentType().contains("image/")) {
        System.out.println("content type" + p.getContentType());
        File f = new File("image" + new Date().getTime() + ".jpg");
        DataOutputStream output = new DataOutputStream(
                new BufferedOutputStream(new FileOutputStream(f)));
        com.sun.mail.util.BASE64DecoderStream test =
                (com.sun.mail.util.BASE64DecoderStream) p
                        .getContent();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = test.read(buffer)) != -1) {
            output.write(buffer, 0, bytesRead);
        }
    }
    else {
        Object o = p.getContent();
        if (o instanceof String) {
            System.out.println("This is a string");
            System.out.println("---------------------------");
            System.out.println((String) o);
        }
        else if (o instanceof InputStream) {
            System.out.println("This is just an input stream");
            System.out.println("---------------------------");
            InputStream is = (InputStream) o;
            is = (InputStream) o;
            int c;
            while ((c = is.read()) != -1)
                System.out.write(c);
        }
        else {
            System.out.println("This is an unknown type");
            System.out.println("---------------------------");
            System.out.println(o.toString());
        }
    }

*/

}

public void writeEnvelope(Message m) throws Exception {
    System.out.println("This is the message envelope");
    System.out.println("---------------------------");
    Address[] a;
    StringBuilder sender = new StringBuilder();
    StringBuilder recipients = new StringBuilder();
    String subject = "";

    // FROM
    if ((a = m.getFrom()) != null) {
        for (int j = 0; j < a.length; j++)
            sender.append(a[j].toString());
    }

    // TO
    if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
        for (int j = 0; j < a.length; j++)
            recipients.append(a[j].toString());
    }

    // SUBJECT
    if (m.getSubject() != null)
        subject = m.getSubject();



    intent.putExtra("Sender", sender.toString());
    intent.putExtra("Recipients", recipients.toString());
    intent.putExtra("Message", subject);
    intent.putExtra("Date", m.getReceivedDate().toString());


}



class ReadEmails extends AsyncTask<String, Void, String> {


    @Override
    protected String doInBackground(String... params) {


        // Create all the needed properties - empty!
        Properties connectionProperties = new Properties();
        // Create the session
        Session session = Session.getDefaultInstance(connectionProperties, null);

        try {
            System.out.print("Connecting to the IMAP server...");
            // Connecting to the server
            // Set the store depending on the parameter flag value
            store = session.getStore("imaps");

            // Set the server depending on the parameter flag value
            String server = "imap.gmail.com";
            store.connect(server, "....@gmail.com", "password");

            System.out.println("done!");

            // Get the Inbox folder
            Folder inbox = store.getFolder("Inbox");

            // Set the mode to the read-only mode
            inbox.open(Folder.READ_ONLY);

            // Get messages
            CheckMail.messages = Arrays.asList(inbox.getMessages());

            System.out.println("Reading messages...");

             sender = new String[messages.size()];
             date = new String[messages.size()];
             subject = new String[messages.size()];
             seen = new boolean[messages.size()];

            for (int i = 0; i < messages.size(); i++) {
                try {
                    Address[] froms = messages.get(i).getFrom();
                    String email = froms == null ? null : ((InternetAddress) froms[0]).getAddress();

                    sender[i] = email;
                    date[i] = messages.get(i).getReceivedDate().toString();
                    subject[i] = messages.get(i).getSubject();


                    Flags flags = messages.get(i).getFlags();
                    Flags.Flag[] sf = flags.getSystemFlags();
                    for (int j = 0; j < sf.length; j++) {
                        if (sf[j] == Flags.Flag.SEEN)
                            seen[i] = true;
                    else
                    seen[i] = false;
                    }


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

            System.out.println("Done reading...");


        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    @Override
    protected void onPostExecute(String result) {

        CustomListAdapter whatever = new CustomListAdapter((Activity) context, sender, date, subject, seen);
        listView = (ListView) findViewById(R.id.listviewID);
        listView.setAdapter(whatever);


        listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position,
                                    long id) {

                try {

                    content.delete(0, content.length());
                    intent = new Intent(context, OpenMail.class);
                    writePart(messages.get(position));
                    intent.putExtra("Content", content.toString());
                    startActivity(intent);

                }
                catch (Exception e)
                {e.printStackTrace();}
            }
        });

    }





}
}

1 个答案:

答案 0 :(得分:0)

由于没有人回答......我在某些应用中通过Javamail显示电子邮件。

我认为你已走上正轨,为列表和观众分别开展活动是一种很好的方法。 [或者单独的片段,因为在平板电脑上你可能想要在同一个屏幕上并排显示列表和正文]

可能出现的情侣问题:

  1. 我会谨慎地将电子邮件内容放在额外的内容中以启动活动和/或将其提交到查看器活动中保存的实例状态,因为存在大小限制[例如,1MB用于保存的实例状态Android 7 +]

  2. 在活动中的ASyncTask中下载电子邮件可能不是最好的方法。我不知道该应用程序的全部目的,但我认为无论用户是否等待,这都应该成功?如果他们的任务离开,ASyncTask将继续运行,但它将保持活动上下文,导致所谓的“临时内存泄漏”。最好将它放在一个服务中并在一个单独的线程中下载它。然而,在活动中将其作为概念证明是完全合理的......

  3. 我不认为在电子邮件列表活动中使用消息结构是最好的方法。在我的应用程序中,我在后台服务中下载电子邮件,并通过ContentProvider将数据提交到SQL-DB。在消息查看器屏幕上,使用名为CursorLoader的组件从ContentProvider / SQL-DB检索电子邮件正文。它处理后台中的所有加载,以便UI在加载大邮件时保持响应。但无论如何,我避免在活动之间传递消息体。

  4. 许多电子邮件都有HTML部分(multipart / alternative:text / plain&amp; text / html),因此查看器实现为WebView。 WebView以最小的努力制作了外观精美的电子邮件。

  5. 在检索邮件时偶然发现其他问题,请注意调用setPeek(true)。它将停止设置READ标志。对于GMail来说这不是问题,但是一些IMAP服务器会设置这个标志。如果除主电子邮件应用程序之外的任何应用程序更改READ标志,用户将会抱怨。也不要假设任何标题存在,垃圾邮件电子邮件因遗漏消息ID,主题和其他字段而臭名昭着。最后,可能值得考虑通过OAuth2实施身份验证,这将使您的应用程序能够通过Javamail连接到用户的GMail帐户,而无需他们的密码。

  6. 我不确定这些是否真的有帮助,因为它是一项相当大的工作,但一步一步......干杯!