iOS邮件开发整理

2023-01-06

iOS邮件开发整理

邮件协议

常见的邮箱协议有 SMTP、POP3、IMAP等

  1. Simple Mail Transfer Protocol(SMTP)

    SMTP是互联网上的一种通讯协议,主要功能是用在传送电子邮件,当我们通过电子邮件程序,寄E-mil给另外一个人时,必须通过SMTP通讯协议,将邮件送到对方的邮件服务器上,等到对方上网的时候,就可以收到你所寄的信

  2. Post Office Protocol 3(POP3)

    POP3是邮局协议的第3个版本,是TCP/IP协议族中的一员(默认端口是110)。本协议主要用于支持使用客户端远程管理在服务器上的电子邮件。,它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议。它是因特网电子邮件的第一个离线协议标准,POP3允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的

  3. Internet Mail Access Protocol(IMAP)

    IMAP提供webmail 与电子邮件客户端之间的双向通信,客户端的操作都会反馈到服务器上,对邮件进行的操作,服务器上的邮件也会做相应的动作

IMAP相对POP3的好处

IMAP 允许你从任何设备访问你的电子邮件,无论你身在何处。 使用 IMAP 阅读电子邮件时,实际上不是在计算机上下载或存储它;而是从电子邮件服务读取它。 因此,你可以从世界上任何地方的不同设备检查你的电子邮件:你的手机、计算机、朋友的计算机。

IMAP 仅在单击邮件时下载邮件,附件不会自动下载。 这样,你就能比 POP 更快地检查邮件。

POP 的工作原理是联系电子邮件服务并从中下载所有新邮件。 下载到电脑或 Mac 后,将从电子邮件服务中删除它们。 这意味着,在下载电子邮件后,只能使用 同一台计算机对其进行访问。 如果尝试从其他设备访问电子邮件,则之前下载的邮件将不可用。

已发送邮件存储在本地电脑或 Mac 上,而不是存储在电子邮件服务器上

简单地说,SMTP管‘发’, POP3/IMAP管‘收’。

邮件的发收过程

写完邮件,点击‘发送’。这时邮件软件会发消息给邮件服务器上的SMTP service。这时有两种情况

  1. 如果邮件的收信人也是处于同一个domain,比如从http://aaa.com 发送给123的邮箱,SMTP service只需要转给local的POP3 Service即可。
  2. 如果邮件收信人是另外的domain,比如 http://aaa.com 发送给http://bbb.com, SMTP service需要通过询问DNS,找到属于bbb的SMTP service的host。

MailCore2 详细使用

MailCore是一个第三方的邮件SDK,支持POP和IMAP 方式接收邮件,以及smtp邮件发送

发邮件

  1. 先创建MCOSMTPSession,配置smtp邮箱参数
MCOSMTPSession *smtpSession = [[MCOSMTPSession alloc] init];  
smtpSession.hostname = @"smtp.exmail.qq.com";  
smtpSession.port = 587;  
smtpSession.username = @"aaa@qq.com";  
smtpSession.password = @"passward";  
smtpSession.connectionType = MCOConnectionTypeStartTLS;  
  
MCOSMTPOperation *smtpOperation = [self.smtpSession loginOperation];  
[smtpOperation start:^(NSError * error) {  
    if (error == nil) {  
        NSLog(@"login account successed");  
    } else {  
        NSLog(@"login account failure: %@", error);  
    }  
}];  
  1. 使用MCOMessageBuilder构建邮件体的发送内容
// 构建邮件体的发送内容  
MCOMessageBuilder *messageBuilder = [[MCOMessageBuilder alloc] init];  
messageBuilder.header.from = [MCOAddress addressWithDisplayName:@"张三" mailbox:@"111111@qq.com"];   // 发送人  
messageBuilder.header.to = @[[MCOAddress addressWithMailbox:@"222222@qq.com"]];       // 收件人(多人)  
messageBuilder.header.cc = @[[MCOAddress addressWithMailbox:@"@333333qq.com"]];      // 抄送(多人)  
messageBuilder.header.bcc = @[[MCOAddress addressWithMailbox:@"444444@qq.com"]];    // 密送(多人)  
messageBuilder.header.subject = @"测试邮件";    // 邮件标题  
messageBuilder.textBody = @"hello world";           // 邮件正文  
  
/*  
 如果邮件是回复或者转发,原邮件中往往有附件以及正文中有其他图片资源, 
 如果有需要你可将原文原封不动的也带过去,这里发送的正文就可以如下配置  
 */  
NSString * bodyHtml = @"<p>我是原邮件正文</p>";  
NSString *body = @"我是邮件回复的内容";  
NSMutableString*fullBodyHtml = [NSMutableString stringWithFormat:@"%@<br/>-------------原始邮件-------------<br/>%@",[body stringByReplacingOccurrencesOfString:@"\n"withString:@"<br/>"],bodyHtml];  
[messageBuilder setHTMLBody:fullBodyHtml];  
  
// 添加正文里的附加资源  
NSArray *inattachments = msgPaser.htmlInlineAttachments;  
for (MCOAttachment*attachmentininattachments) {  
    [messageBuilder addRelatedAttachment:attachment];    //添加html正文里的附加资源(图片)  
}  
  
// 添加邮件附件  
for (MCOAttachment*attachmentinattachments) {  
    [builder addAttachment:attachment];    //添加附件  
}  

  1. 将构建好的邮件发送出去
// 发送邮件  
NSData * rfc822Data =[messageBuilder data];  
MCOSMTPSendOperation *sendOperation = [self.smtpSession sendOperationWithData:rfc822Data];  
[sendOperation start:^(NSError *error) {  
    if (error == nil) {  
        NSLog(@"send message successed");  
    } else {  
        NSLog(@"send message failure: %@", error);  
    }  
}];  

收邮件

  1. 先创建MCOIMAPSession,配置imap邮箱参数
MCOIMAPSession *imapSession = [[MCOIMAPSession alloc] init];  
imapSession.hostname = hostname;  
imapSession.port = port;  
imapSession.username = username;  
imapSession.password = passward;  
imapSession.connectionType = MCOConnectionTypeTLS;  
  
MCOIMAPOperation *imapOperation = [imapSession checkAccountOperation];  
[imapOperation start:^(NSError * __nullable error) {  
    if (error == nil) {  
        NSLog(@"login account successed\n");  
          
        // 在这里获取邮件,获取文件夹信息  
        [self loadIMAPFolder];  
    } else {  
        NSLog(@"login account failure: %@\n", error);  
    }  
}];  

  1. 获取文件夹目录
MCOIMAPFetchFoldersOperation *imapFetchFolderOp = [imapSession fetchAllFoldersOperation];  
[imapFetchFolderOp start:^(NSError * error, NSArray * folders) {  
    [_folderList addObjectsFromArray:folders];  
    [_folderTableView reloadData];  
}];  
  1. 获取收件箱邮件
MCOIMAPMessagesRequestKind requestKind = (MCOIMAPMessagesRequestKind)  
(MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure |  
 MCOIMAPMessagesRequestKindInternalDate | MCOIMAPMessagesRequestKindHeaderSubject |  
 MCOIMAPMessagesRequestKindFlags);  
  
// 获取收件箱信息(包含邮件总数等信息)  
NSString *folderName = @"INBOX";  
MCOIMAPFolderInfoOperation * folderInfoOperation = [imapSession folderInfoOperation:folderName];  
[folderInfoOperation start:^(NSError *error, MCOIMAPFolderInfo * info) {  
      
    NSLog(@"total number: %d", info.messageCount);  
      
    NSInteger numberOfMessages = 10;  
    numberOfMessages -= 1;  
    MCOIndexSet *numbers = [MCOIndexSet indexSetWithRange:MCORangeMake([info messageCount] - numberOfMessages, numberOfMessages)];  
      
    MCOIMAPFetchMessagesOperation *imapMessagesFetchOp = [imapSession fetchMessagesByNumberOperationWithFolder:folderName  
                                                                                                                                                                  requestKind:requestKind  
                                                                                                                                                                        numbers:numbers];  
      
    // 异步获取邮件  
    [imapMessagesFetchOp start:^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages) {  
        [_messageList addObjectsFromArray:messages];  
        [_messageTableView reloadData];  
    }];  
}];  

  1. 获取邮件头
// 拿出一个邮件MCOIMAPMessage(里面包含邮件头等信息)  
MCOIMAPMessage *message = _messageList [0];  
  
// 使用MCOIMAPMessageRenderingOperation来获得邮件概要信息  
NSString *uidKey = [NSString stringWithFormat:@"%d", message.uid];  
  
MCOIMAPMessageRenderingOperation *messageRenderingOperation = [imapSession plainTextBodyRenderingOperationWithMessage:message folder:@"INBOX"];  
[messageRenderingOperation start:^(NSString * plainTextBodyString,NSError * error) {  
      
    // plainTextBodyString为邮件的正文文本信息  
      
}];  
  1. 获取邮件内容,用MCOMessageParser解析邮件
MCOIMAPFetchContentOperation * fetchContentOp = [self.imapSession fetchMessageOperationWithFolder:@"INBOX" uid:[message uid]];  
[fetchContentOp start:^(NSError * error, NSData * data) {  
   if ([error code] != MCOErrorNone) {  
       return;  
   }  
     
   // 解析邮件内容  
   MCOMessageParser * msgPareser = [MCOMessageParser messageParserWithData:data];  
   NSString *content = [msgPareser htmlRenderingWithDelegate:self];  
];