Android平台邮件自动发送功能实现
原文链接 https://jamling.github.io/2012/03/01/Android-Android-send-email-background/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
简介
本文简述的是在Android平台如何自动发送邮件(没有邮件编写界面),主要应用场景为忘记密码等安全等级较高的操作,比如我忘记密码了,点击“发送密码到我的邮箱”系统会将密码发送到注册时的电子邮件地址。 <!-- more -->
Android平台邮件客户端
- Gmail: Gmai电子邮件客户端
- Email: 通用的电子邮件客户端
解决方案
Gmail
Gmail已经支持自动发送了,所以非常简单。在使用时,需要添加
<uses-permission android:name="com.google.android.gm.permission.AUTO_SEND" />
到AndroidManifest.xml
示例代码如下:
Intent intent = new Intent("com.google.android.gm.action.AUTO_SEND");
intent.setType("plain/text");
String[] reciver = new String[] { "xxxx@xxx.com" };
String subject = "email title";
String body = "email body";
intent.putExtra(android.content.Intent.EXTRA_EMAIL, reciver);
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
intent.putExtra(android.content.Intent.EXTRA_TEXT, body);
Email不支持自动发送,但又是默认邮件客户端,所以需要添加自动发送功能。主要实现步骤为:
编写一个自动发送邮件类
主要功能为:接收用户输入,组装message对象,获取Sender实例,将message发送出去,最后删除message对象(这样已发送的邮件内容不会出现在client中,提高发安全性)
Java代码
package com.android.email.activity;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.net.Uri;
import android.widget.Toast;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.mail.Address;
import com.android.emailcommon.utility.Utility;
import com.android.emailcommon.mail.AuthenticationFailedException;
import com.android.email.EmailAddressValidator;
import com.android.email.mail.Sender;
/**
* Send email in background with account configured in Email application.
* Sending message will not saved as draft or in out-going box. Usage:
*
* <pre>
* Intent intent = new Intent("com.android.email.intent.action.sendInBack");
* String[] reciver = new String[] { "your_name@corp.com" };
* String subject = "email title";
* String body = "email body ";
* intent.putExtra(android.content.Intent.EXTRA_EMAIL, reciver[0]);
* intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
* intent.putExtra(android.content.Intent.EXTRA_TEXT, body);
* startActivityForResult(Intent.createChooser(intent, "send"), 0x02);
* </pre>
*
* Now, attachment and multi-receiver function is unsupported.
*
* @author melord
*
*/
public class EmailSendAutoActivity extends Activity implements SendListener {
private static String tag = "EmailSendAutoAcitivity";
private Context mContext;
private String mTo;
private String mCc;
private String mBcc;
private String mSubject;
private String mBody;
private EmailAddressValidator mValidator = new EmailAddressValidator();
private SendListener mListener;
private Toast mWaiting;
private boolean enableLog = true;
/**
* Sending account email address.
*/
private String mSendEmail;
/**
* Sending account id
*/
private long mAccountId = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mContext = this;
requestWindowFeature(Window.FEATURE_NO_TITLE);
mListener = this;
Intent intent = getIntent();
initMessageFromIntent(intent);
initAccountFromIntent(intent);
new SendTask().execute();
String msg = intent.getStringExtra("sendMsg");
if (msg == null) {
msg = "Sending message...";
}
// mWaiting = ProgressDialog.show(this, "", "sending...", true, true,
// null);
mWaiting = Toast.makeText(this, msg, Toast.LENGTH_LONG);
mWaiting.show();
}
@Override
public void onBackPressed() {
if (mWaiting != null) {
mWaiting.cancel();
}
super.onBackPressed();
}
@Override
public void finish() {
if (mWaiting != null) {
mWaiting.cancel();
}
super.finish();
}
/**
* Initialize sending account from intent.
*
* @param intent
* imcoming intent
*/
private void initAccountFromIntent(Intent intent) {
String email = intent.getStringExtra("sendAccount");
if (email != null) {
log(String.format("send email use account (%s) ", email));
mSendEmail = email;
Long[] ids = EmailContent.Account.getAllAccountIds(this);
if (ids != null && ids.length > 0) {
for (int i = 0; i < ids.length; i++) {
EmailContent.Account temp = EmailContent.Account
.restoreAccountWithId(this, ids[i]);
if (temp != null && email.equals(temp.getEmailAddress())) {
log("valid account");
mAccountId = ids[i];
break;
}
}
}
}
}
/**
* Initialize message from intent.
*
* @param intent
* intent
*/
private void initMessageFromIntent(Intent intent) {
String to = intent.getStringExtra(Intent.EXTRA_EMAIL);
mTo = composeAddress(to);
String cc = intent.getStringExtra(Intent.EXTRA_CC);
mCc = composeAddress(cc);
String bcc = intent.getStringExtra(Intent.EXTRA_BCC);
mBcc = composeAddress(bcc);
mSubject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
mBody = intent.getStringExtra(Intent.EXTRA_TEXT);
log("to:" + mTo);
log("cc:" + mCc);
log("bcc:" + mBcc);
}
/**
* change to stand email address reference to Rfc822
*
* @param address
* email address
* @return RFC822 format email address
*/
private String composeAddress(String address) {
String addr = null;
if (!TextUtils.isEmpty(address)) {
Address[] addresses = Address.parse(address.trim());
addr = Address.pack(addresses);
}
return addr;
}
/**
* Update message. fill fields.
*
* @param message
* email message
* @param account
* sending account
*/
private void updateMessage(Message message, Account account) {
if (message.mMessageId == null || message.mMessageId.length() == 0) {
message.mMessageId = Utility.generateMessageId();
}
message.mTimeStamp = System.currentTimeMillis();
// it will : Name<Address>
message.mFrom = new Address(account.getEmailAddress(), account
.getSenderName()).pack();
message.mTo = mTo;
message.mCc = mCc;
message.mBcc = mBcc;
message.mSubject = mSubject;
message.mText = mBody;
message.mAccountKey = account.mId;
// here just used account setting simply
message.mDisplayName = account.getSenderName();
message.mFlagRead = true;
message.mFlagLoaded = Message.FLAG_LOADED_COMPLETE;
}
private void log(String msg) {
if (enableLog) {
Log.i(tag, msg);
}
}
/**
* Really send message.
*
* @param account
* sending account
* @param messageId
* message id
*/
public void sendMessage(Account account, long messageId) {
// message uri
Uri uri = ContentUris.withAppendedId(EmailContent.Message.CONTENT_URI,
messageId);
try {
// get a sender, ex. smtp sender.
Sender sender = Sender.getInstance(mContext, account
.getSenderUri(mContext));
// sending started
mListener.onStarted(account.mId, messageId);
// sending
sender.sendMessage(messageId);
// send completed
mListener.onCompleted(account.mId);
} catch (MessagingException me) {
// report error
mListener.onFailed(account.mId, messageId, me);
} finally {
try {
// delete this message whenever send successfully or not
mContext.getContentResolver().delete(uri, null, null);
} catch (Exception ex) {
Log.w(tag, "delete message occur exception message uri:" + uri);
}
}
}
public void onCompleted(long accountId) {
log("send mail ok");
// return Activity.RESULT_OK when send successfully
setResult(RESULT_OK);
finish();
}
public void onFailed(long accountId, long messageId, Exception ex) {
log("send mail failed : " + ex.toString());
finish();
}
public void onStarted(long messageId, long accountId) {
log("send mail started");
}
/**
* Send message task, it is an async task
*
* @author melord_li
*
*/
private class SendTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
// get default account, if not set, first record is treated as
// default.
// long id = Account.getDefaultAccountId(mContext);
long id = mAccountId;
if (id < 0) {
id = Account.getDefaultAccountId(mContext);
}
if (id < 0) {
Log.w(tag, "no account exists");
finish();
return null;
}
// get full account message
Account account = Account.restoreAccountWithId(mContext, id);
// A empty message
Message message = new Message();
// fill message field
updateMessage(message, account);
// Save this message. Because send API will read message in message
// db.
Uri uri = message.save(mContext);
if (uri == null) {
Log.e(tag, "save message occured an error");
finish();
return null;
}
// send
sendMessage(account, message.mId);
return null;
}
}
}
/**
* Sending monitor
*
* @author melord
*
*/
interface SendListener {
/**
* Send failed.
*
* @param accountId
* account id
* @param messageId
* message id
* @param ex
* exception
*/
void onFailed(long accountId, long messageId, Exception ex);
/**
* Send begin.
*
* @param accountId
* account id
* @param messageId
* message id
*/
void onStarted(long messageId, long accountId);
/**
* Send completed.
*
* @param accountId
* account id
*/
void onCompleted(long accountId);
}
配置
Xml代码
<activity android:name=".activity.EmailSendAutoActivity" android:theme="@android:style/Theme.Translucent">
<intent-filter>
<action android:name="com.android.email.intent.action.sendInBack"/>
<data android:mimeType="*/*" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
使用
Java代码
Intent intent = new Intent("com.android.email.intent.action.sendInBack");
String[] reciver = new String[] { "yourname@corp.com" };
String subject = "email title";
String body = "email body";
intent.putExtra(android.content.Intent.EXTRA_EMAIL, reciver[0]);
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
intent.putExtra(android.content.Intent.EXTRA_TEXT, body);
startActivityForResult(Intent.createChooser(intent, "send"), 0x02);
处理回调
如果发送成功,会返回Activity.RESULT_OK。