邮箱开发

前记:本文章是邮箱开发协议层开发的说明文档,并结合IOS MailCore 2框架进行比对学习,以期对邮箱开发有更好的理解。

第一章 IMAP

1、IMAP简介

1.1 IMAP 和 POP区别

1)、POP不能方便的处理多个信箱,IMAP可通过提供多个远程信箱的访问和在远程服务器上保留全部信件的能力。
2)、POP不能很好的解决多客户端对同一信箱的访问。IMAP支持多个用户作为不同标识访问同一文件夹。
3)、IMAP支持信件和MIME结构,客户端不需要做复杂的信件结构分析。

1.2 接口模型

1)、MUA,MTA与MDA基本概念

MUA(Mail User Agent):顾名思义,MUA就是“邮件用户代理”。邮件需要代理,这是由于通常Client端的计算机无法直接寄信(不然为什么要邮件主机?),所以,需要通过MUA帮我们传递信件,不论是送信还是收信,Client端用户都需要通过各个操作系统提供的MUA才能够使用邮件系统。举个例子,Windows里的OutLook Express、Netscape里的mail功能与KDE里的Kmail都是MUA。MUA主要的功能就是接收邮件主机的电子邮件,并提供用户浏览与编写邮件的功能。
MTA(Mail Transfer Agent):MUA是用在Client端的软件,而MTA是用在邮件主机上的软件,它也是主要的邮件服务器。MTA就是“邮件传送代理”的意思,既然是“传送代理”,那么用户寄信与收信时,都找MTA就对了!因为它负责帮用户传送。基本上,MTA的功能如下。
接收外部主机寄来的信件:既然是邮件主机,接收信件自然是主要功能,只要这个信件里有MTA内部账号,这封信就会被MTA收下来;
帮用户发(寄出)信:既然可以收信,自然也可以发信,只要用户具有合法的使用MTA的权力,就可以利用这台MTA主机把信传送出去!不过要注意,MTA会将信件送给目的地的MTA而不是目的地的MUA。不要搞错了!
曾经有个朋友跟我说,要我传数据给他,因为他要接收我的信件,所以他的计算机(指的是Windows那个Client端计算机)得一直开着,真是不方便!听到这句话时,我吓了一跳——这个概念是不对的,因为用户使用的是MUA,而信件仅会送达MTA主机上,收、发信件时,都需要通过MTA帮忙处理,所以,用户在使用邮件编辑器“MUA”将数据编辑完毕之后,按下送出,并且成功送到MTA之后,接下来的事情就是MTA的工作了,跟用户的Client端计算机没有关系。
用户收自己的信:用户可以将放置在邮件主机的信件收到自己的个人计算机上。
MDA(Mail Delivery Agent):“邮件投递代理”主要的功能就是将MTA接收的信件依照信件的流向(送到哪里)将该信件放置到本机账户下的邮件文件中(收件箱),或者再经由MTA将信件送到下个MTA。如果信件的流向是到本机,这个邮件代理的功能就不只是将由MTA传来的邮件放置到每个用户的收件箱,它还可以具有邮件过滤(filtering)与其他相关功能。


IMAP接口模型

如图所示:MTA接收到达的电子邮件、并把它提交给一个MDA,由它把电子邮件投递给一个信箱。IMAP客户机管理它的本地信箱,并与IMAP服务器通信管理它的远程信箱。IMAP服务器提供了一个远程客户机与存放在服务器上的信箱之间的接口。
IMAP允许多个客户机同时访问同一个信箱,如果一个客户机删除里一个客户机已经选择的信箱中的信件,IMAP服务器会通知客户机的变化。

1.3 协议状态

IMAP会话状态

客户机一旦连接到服务器,服务器就会输出一个连接问候,客户机使用这个问候确定服务器是否愿意进行对话,以及服务器所处的状态。
会话通常从未验证状态开始,除非会话已经预先进行验证。在这个状态中,只需要少量的命令来验证。
在客户机对服务器确认身份后,会话进入已验证状态,这时有更多的命令可以使用。为了使用特定的信箱,客户机必须发出select或者examine命令进入select(选择)状态。如果命令失败,会话保持在selected状态中。一旦处于authenticated状态,它保持在那里,直到准备终止,或者发出close命令。
最后的状态是logout(注销),它是准备连接终止。当客户机发出logout命令,或者在服务器决定关闭连接时,进入这个状态。

1.4 命令和应答

  • IMAP仅仅规定了一个超时值,一个不活动自动注销的定时器,限制客户机的空闲时间。
  • 命令行和应答行不区分大小写。

1.5 状态应答

状态应答是服务器发送命令或会话状态给客户机的主要途径。

  • 两种类型的状态应答
    1)、标记状态应答
    标记状态应答也称为完整状态应答,在应答行的第一个字段含有一个标记,指示特定的命令是成功、失败,还是其他类型的协议错误。
    2)、非标记状态应答
    非标记应答在应答行的第一个字段含有一个“*”字符,传递与特定的命令不直接关联的信息。包括状态应答和服务器数据。
  • 常用应答状态码
    1)、OK应答
    OK应答有两种用法。当在标记应答中使用时,它指示该标记标识的命令成功的完成。当在非标记应答中,它是来自服务器的信息信件,可以是任意想要的类型。
eg: a042 noop
标记状态应答:
a042 ok noop completed
非标记状态应答:
 * OK imap.example.com server ready

2)、NO应答

eg:a030 create team-notes
标记状态应答:
a030 no mailbox already esists
非标记状态应答:
* no [alert] MailBox is at 95% quota  

3)、BAD应答

eg:a1035 noop blurp
标记状态应答:
a1035 bad invalid argument 
非标记状态应答:
* bad missing tag 

4)、PREAUTH应答

PREAUTH 状态应答仅在会话开始的时候看到,仅作为非标记应答发送
e.g
* preauth localhost server ready

5)、BYE应答

仅作为非标记应答发送
e.g
* bye server loging out 

1.6 服务器数据

1)、简介
定义:除应答状态外,服务器也可以发送服务器数据。且服务器数据总是非标记的。
组成: 信件文件、信件标志、信箱列表、搜索结果和服务器功能等。
具体的关键字会在后面章节介绍。

1.7 关于多个等待处理的命令

  • SMTP支持命令的顺序执行(流水线)。
  • SMTP还支持多个等待命令按任意顺序处理(非流水线处理)。
    在非流水线处理模式中:需注意多个命令不引入二义性
假设同时发出一个rename 和 create命令
//1、按顺序执行
b285 rename status-reports status-reports-old
b286 create status-reports
// 执行结果
b285 OK rename completed
b286 OK create completed
//2、加入命令按相反顺序执行
b285 rename status-reports status-reports-old
b286 create status-reports
// 执行结果
b286 no mailbox already exitsts
b285 OK rename completed

2、IMAP数据对象

2.1 NIL

表示不存在的值的地方使用的一个符号。

2.2 邮箱名

  • 信箱名是IMAP中的文字量,使用一个字符串作为语法元素。
  • 在各大厂商中的邮件协议中只有一个特殊的信箱名:INBOX,这是指用于存储到达电子邮箱的主信箱。且不区分大小写。
  • 在各大厂商的其他(除INBOX)的邮箱名可能不禁相同,比如有的厂商的发送箱写作:Send Mail但是可能其他厂商会写作:send-mail。

2.3 内部日期

表示当一个电子邮件加载到信箱中时,指定的一个内部日期,即收到(或发送)信件的时间和日期。

2.4 大小

表示邮件数据大小的数值。

2.5 sequence-num

  • 用来标识当前信件在整个信件集合中的位置。
  • 需要注意的是:某个信件在信件集合中的位置不是一成不变的,一个具体的例子,当用用户在A客户端登录,他对信件标号为5的信件感兴趣,端来A客户端,在B客户端中登录他删除的了信件标号为2的信件,此时再次登录A客户端时,原来标识为5 的信件将会被更改为4。这在信箱的数据缓存时应有相应的策略来解决这个问题。

2.6 唯一标识符 UID

  • 概念:信件放在信箱中时,IMAP给每个信件指定的一个唯一的标识符。
  • 类型:32位整数
  • 唯一标识符按递增的顺序进行分配,但是不要求是连续的,但这些数字必须是升序的。
  • 不变性:不管邮箱中信件的增删都不会影响邮件的唯一标识符的改变。

2.7 信件标志

  • 概念:用来标识一个邮件的信息状态。常见的标志有:新邮件、已阅邮件、已读邮件、未读邮件、删除邮件、星标邮件。
  • 用户在客户端开发时可进行自定义的邮件。
@interface MCOIMAPMessage : MCOAbstractMessage <NSCoding>

/** IMAP UID of the message. */
@property (nonatomic, assign) uint32_t uid;

/** IMAP sequence number of the message.
 @warning *Important*: This property won't be serialized. */
@property (nonatomic, assign) uint32_t sequenceNumber;

/* Size of the entire message */
@property (nonatomic, assign) uint32_t size;

/** Flags of the message, like if it is deleted, read, starred etc */
@property (nonatomic, assign) MCOMessageFlag flags;

/** The contents of the message flags when it was fetched from the server */
@property (nonatomic, assign) MCOMessageFlag originalFlags;

/** Flag keywords of the message, mostly custom flags */
@property (nonatomic, copy) NSArray * /* NSString */ customFlags;

/** It's the last modification sequence value of the message synced from the server. See RFC4551 */
@property (nonatomic, assign) uint64_t modSeqValue;

/** Main MIME part of the message */
@property (nonatomic, retain) MCOAbstractPart * mainPart;

/** All Gmail labels of the message */
@property (nonatomic, copy) NSArray * /* NSString */ gmailLabels;

/** Gmail message ID of the message */
@property (nonatomic, assign) uint64_t gmailMessageID;

/** Gmail thread ID of the message */
@property (nonatomic, assign) uint64_t gmailThreadID;

/**
 Returns the part with the given part identifier.
 @param partID A part identifier looks like 1.2.1
*/
- (MCOAbstractPart *) partForPartID:(NSString *)partID;

/**
 HTML rendering of the message to be displayed in a web view.
 The delegate should implement at least
 [MCOAbstractMessage:dataForIMAPPart:folder:]
 so that the complete HTML rendering can take place.
*/
- (NSString *) htmlRenderingWithFolder:(NSString *)folder
                              delegate:(id <MCOHTMLRendererIMAPDelegate>)delegate;

@end

2.8 信件结构

  • 关键字段列表
1、 Date(发送或收件时间,date类型)
2、 Subject (主题,字符串类型)
3、 From (信件来自,地址类型)
4、 Sender (发送者,地址类型)
5、 Reply-To (回复,数组类型,数组元素为地址类型)
6、 To (发送至,数组类型,数组元素为地址类型)
7、 Cc (抄送,数组类型,数组元素为地址类型)
8、 Bcc (密送,数组类型,数组元素为地址类型)
9、 Message-ID (信件标志,字符串类型)
  • 由上面可见Subject、Message-ID是字符串类型,而From、Sender、From、To、Cc、Bcc 都是地址类型。以下是MailCore 2框架中MCOMessageHeader中的参数,从中可以看出更详细的关于邮箱Header的信息。
@interface MCOMessageHeader : NSObject <NSCopying, NSCoding>

/** Message-ID field.*/
@property (nonatomic, copy) NSString * messageID;

/** Message-ID auto-generated flag.*/
@property (nonatomic, readonly, getter=isMessageIDAutoGenerated) BOOL messageIDAutoGenerated;

/** References field. It's an array of message-ids.*/
@property (nonatomic, copy) NSArray * /* NSString */ references;

/** In-Reply-To field. It's an array of message-ids.*/
@property (nonatomic, copy) NSArray * /* NSString */ inReplyTo;

/** Date field: sent date of the message.*/
@property (nonatomic, strong) NSDate * date;

/** Received date: received date of the message.*/
@property (nonatomic, strong) NSDate * receivedDate;

/** Sender field.*/
@property (nonatomic, copy) MCOAddress * sender;

/** From field: address of the sender of the message.*/
@property (nonatomic, copy) MCOAddress * from;

/** To field: recipient of the message. It's an array of MCOAddress.*/
@property (nonatomic, copy) NSArray * /* MCOAddress */ to;

/** Cc field: cc recipient of the message. It's an array of MCOAddress.*/
@property (nonatomic, copy) NSArray * /* MCOAddress */ cc;

/** Bcc field: bcc recipient of the message. It's an array of MCOAddress.*/
@property (nonatomic, copy) NSArray * /* MCOAddress */ bcc;

/** Reply-To field. It's an array of MCOAddress.*/
@property (nonatomic, copy) NSArray * /* MCOAddress */ replyTo;

/** Subject of the message.*/
@property (nonatomic, copy) NSString * subject;

/** Email user agent name: X-Mailer header.*/
@property (nonatomic, copy) NSString * userAgent;

/** Returns a header created from RFC 822 data.*/
+ (MCOMessageHeader *) headerWithData:(NSData *)data;

/** Initialize a header with RFC 822 data.*/
- (instancetype) initWithData:(NSData *)data;

/** Adds a custom header.*/
- (void) setExtraHeaderValue:(NSString *)value forName:(NSString *)name;

/** Remove a given custom header.*/
- (void) removeExtraHeaderForName:(NSString *)name;

/** Returns the value of a given custom header.*/
- (NSString *) extraHeaderValueForName:(NSString *)name;

/** Returns an array with the names of all custom headers.*/
- (NSArray * /* NSString */) allExtraHeadersNames;

/** Extracted subject (also remove square brackets).*/
- (NSString *) extractedSubject;

/** Extracted subject (don't remove square brackets).*/
- (NSString *) partialExtractedSubject;

/** Fill the header using the given RFC 822 data.*/
- (void) importHeadersData:(NSData *)data;

/** Returns a header that can be used as a base for a reply message.*/
- (MCOMessageHeader *) replyHeaderWithExcludedRecipients:(NSArray * /* MCOAddress */)excludedRecipients;

/** Returns a header that can be used as a base for a reply all message.*/
- (MCOMessageHeader *) replyAllHeaderWithExcludedRecipients:(NSArray * /* MCOAddress */)excludedRecipients;

/** Returns a header that can be used as a base for a forward message.*/
- (MCOMessageHeader *) forwardHeader;

@end
// 地址结构是用圆括号列表表示:
liuweihua<645565656@qq.com>
//圆括号表示为:
("liuweihua" NIL "645565656" "qq.com")
// 说明
// 地址结构是有个圆括号列表好友电子邮件地址的分析元素。这些元素
// 按照个人按照个人名称、SMTP、源路由、信箱名、和域名列出
  • 地址结构


    地址列表

一下摘自MailCore 2 MCOAddress(地址结构类的接口文档)从中可以更好的看出地址结构的内容。

@interface MCOAddress : NSObject <NSCopying, NSCoding>

/** Creates an address with a display name and a mailbox.

    Example: [MCOAddress addressWithDisplayName:@"DINH Viêt Hoà" mailbox:@"hoa@etpan.org"] */
+ (MCOAddress *) addressWithDisplayName:(NSString *)displayName
                                mailbox:(NSString *)mailbox;

/** Creates an address with only a mailbox.

    Example: [MCOAddress addressWithMailbox:@"hoa@etpan.org"]*/
+ (MCOAddress *) addressWithMailbox:(NSString *)mailbox;

/** Creates an address with a RFC822 string.

    Example: [MCOAddress addressWithRFC822String:@"DINH Vi=C3=AAt Ho=C3=A0 <hoa@etpan.org>"]*/
+ (MCOAddress *) addressWithRFC822String:(NSString *)RFC822String;

/** Creates an address with a non-MIME-encoded RFC822 string.

    Example: [MCOAddress addressWithNonEncodedRFC822String:@"DINH Viêt Hoà <hoa@etpan.org>"]*/
+ (MCOAddress *) addressWithNonEncodedRFC822String:(NSString *)nonEncodedRFC822String;

/** 
 Returns an NSArray of MCOAddress objects that contain the parsed
 forms of the RFC822 encoded addresses.

 For example: @[ @"DINH Vi=C3=AAt Ho=C3=A0 <hoa@etpan.org>" ]*/
+ (NSArray *) addressesWithRFC822String:(NSString *)string;

/** 
 Returns an NSArray of MCOAddress objects that contain the parsed
 forms of non-encoded RFC822 addresses.

 For example: @[ "DINH Viêt Hoà <hoa@etpan.org>" ]*/
+ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string;


/** Returns the display name of the address.*/
@property (nonatomic, copy) NSString * displayName;

/** Returns the mailbox of the address.*/
@property (nonatomic, copy) NSString * mailbox;

/** Returns the RFC822 encoding of the address.

    For example: "DINH Vi=C3=AAt Ho=C3=A0 <hoa@etpan.org>"*/
- (NSString *) RFC822String;

/** Returns the non-MIME-encoded RFC822 encoding of the address.

    For example: "DINH Viêt Hoà <hoa@etpan.org>"*/
- (NSString *) nonEncodedRFC822String;

  • 信件结构体
    IMAP在云括号列表中提供了另外一种数据结构,即信件体结构,它是信件的MIME结构的分析表示。
    主要分为:非多部件(nom-multipart)和多部件(multipart)两个主要结构。
//MIME  媒体类型
//Content-Type 内容类型
//Content-ID  内容ID
//Content-Description 内容描述
//Content-Transfer-Encoding  传输加密方式
typedef NS_ENUM(NSInteger, MCOEncoding) {
    /** 7bit encoding.*/
    MCOEncoding7Bit = 0,            /** should match MAILIMAP_BODY_FLD_ENC_7BIT*/
    /** 8bit encoding.*/
    MCOEncoding8Bit = 1,            /** should match MAILIMAP_BODY_FLD_ENC_8BIT*/
    /** binary encoding.*/
    MCOEncodingBinary = 2,          /** should match MAILIMAP_BODY_FLD_ENC_BINARY*/
    /** base64 encoding.*/
    MCOEncodingBase64 = 3,          /** should match MAILIMAP_BODY_FLD_ENC_BASE64*/
    /** quoted-printable encoding.*/
    MCOEncodingQuotedPrintable = 4, /** should match MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE*/
    /** other encoding.*/
    MCOEncodingOther = 5,           /** should match MAILIMAP_BODY_FLD_ENC_OTHER*/
    
    /** Negative values should be used for encoding not supported by libetpan.*/
    
    /** UUEncode encoding.*/
    MCOEncodingUUEncode = -1
};
@interface MCOIMAPPart : MCOAbstractPart <NSCoding>

/** A part identifier looks like 1.2.1 */
@property (nonatomic, copy) NSString * partID;

/** The size of the single part in bytes */
@property (nonatomic, nonatomic) unsigned int size;

/** It's the encoding of the single part */
@property (nonatomic, nonatomic) MCOEncoding encoding;

/**
 Returns the decoded size of the part.
 For example, for a part that's encoded with base64, it will return actual_size * 3/4.
*/
- (unsigned int) decodedSize;

@end

3、标准命令

3.1 capability

// capability 命令返回服务器功能的列表,包括版本信息,以及支持的验证机制和扩展。
tag SP "capability"
//服务器应答:
"*" SP "capability" 1* (SP capalibity-item)
// MailCore 2 提供了相应的接口
/**
 Returns an operation to request capabilities of the server.
 See MCOIMAPCapability for the list of capabilities.

     canIdle = NO;
     MCOIMAPCapabilityOperation * op = [session capabilityOperation];
     [op start:^(NSError * __nullable error, MCOIndexSet * capabilities) {
       if ([capabilities containsIndex:MCOIMAPCapabilityIdle]) {
         canIdle = YES;
       }
     }];
*/
- (MCOIMAPCapabilityOperation *) capabilityOperation;

3.2 noop

// 什么也不做总是成功,如果客户机没有其他命令需要发送的话,
//它可以使用这个命令周期性的查询状态更新,也可以用于复位不活动的自动注销定时器
tag SP "noop"
//MailCore 2 也提供了相应的接口信息
/**
 Returns an operation that will perform a No-Op operation on the given IMAP server.

 MCOIMAPOperation * op = [session noopOperation];
 [op start:^(NSError * __nullable error) {
 ...
 }];
 */
- (MCOIMAPOperation *) noopOperation;

3.3 Logout

// 退出IMAP会话,服务器发送一个BYE应答行,然后关闭连接。
tag SP "logout"
// MailCore 2 也提供了相应的接口信息

/**
 Returns an operation to disconnect the session.
 It will disconnect all the sockets created by the session.

    MCOIMAPOperation * op = [session disconnectOperation];
    [op start:^(NSError * __nullable error) {
       ...
    }];
 */
- (MCOIMAPOperation *) disconnectOperation;

3.4 Login

tag SP "login" SP user-name SP password
//login用于验证客户端,如果该命令成功,会话状态进入
//authenticated,如果因为某个原因导致登录失败,
//服务器发送NO应答,并保持noauthenticated状态。
//MailCore 2 提供了相应的接口
/**
 Returns an operation that will check whether the IMAP account is valid.

     MCOIMAPOperation * op = [session checkAccountOperation];
     [op start:^(NSError * __nullable error) {
          ...
     }];
*/

- (MCOIMAPOperation *) checkAccountOperation;

3.5 creat

// creat 命令在服务器上创建制定的信箱。
// 如果该信箱已经存在,则这个命令将失效。
// mailCore 2 中相应的代码示例为:
 /**
 Returns an operation that creates a new folder

     MCOIMAPOperation * op = [session createFolderOperation:@"holidays 2013"];
     [op start:^(NSError * __nullable error) {
          ...
     }];
*/
- (MCOIMAPOperation *) createFolderOperation:(NSString *)folder;

3.6 delete

//delete 删除指定的邮箱
//MailCore 2 提供了相应的接口:
/**
 Create an operation for deleting a folder

     MCOIMAPOperation * op = [session deleteFolderOperation:@"holidays 2009"];
     [op start:^(NSError * __nullable error) {
          ...
     }]];
*/
- (MCOIMAPOperation *) deleteFolderOperation:(NSString *)folder;

3.7 rename

// 改变信箱的名称
//MailCore 2 提供了相应的接口:
/**
 Creates an operation for renaming a folder

     MCOIMAPOperation * op = [session renameFolderOperation:@"my documents" otherName:@"Documents"];
     [op start:^(NSError * __nullable error) {
        ...
     }];

*/
- (MCOIMAPOperation *) renameFolderOperation:(NSString *)folder otherName:(NSString *)otherName;

3.8 status

// 返回指定信箱的状态信息
//关键字:
// messages:信箱中的心剑术
// recent :最近信件数
// uidnext:将分配给新邮件的下一个uid
// uidvalidity:信箱的唯一合法性值
// unseen: 未读新建的标识
// mailCore 2 给出相应的接口:
/**
 Returns an operation that retrieves folder status (like UIDNext - Unseen -)

    MCOIMAPFolderStatusOperation * op = [session folderStatusOperation:@"INBOX"];
    [op start:^(NSError *error, MCOIMAPFolderStatus * info) {
        NSLog(@"UIDNEXT: %lu", (unsigned long) [info uidNext]);
        NSLog(@"UIDVALIDITY: %lu", (unsigned long) [info uidValidity]);
        NSLog(@"messages count: %lu", [info totalMessages]);
    }];
 */

- (MCOIMAPFolderStatusOperation *) folderStatusOperation:(NSString *)folder;

3.9 select/examine

// 打开信箱进行读写访问,允许访问其中的信件

3.10 close

关闭目前选择的信箱,如果信箱是可写的,它还清理设置为删除标志的信件。

3.11 subscribe

// 在某些情况下,List命令并不适合获取邮箱列表,例如在服务器可能
有几千个新闻组,新闻阅读客户端提供预定和取消预定的能力,允许用户
避免查看不感兴趣的新闻组。这时可通过预定(subscribe)来进行邮件的预定
/**
 Returns an operation to subscribe to a folder.

     MCOIMAPOperation * op = [session createFolderOperation:@"holidays 2013"];
     [op start:^(NSError * __nullable error) {
       if (error != nil)
         return;
       MCOIMAPOperation * op = [session subscribeFolderOperation:@"holidays 2013"];
       ...
     }];
*/
- (MCOIMAPOperation *) subscribeFolderOperation:(NSString *)folder;

3.12 unsubscribe

// 取消预定
/**
 Returns an operation to unsubscribe from a folder.

     MCOIMAPOperation * op = [session unsubscribeFolderOperation:@"holidays 2009"];
     [op start:^(NSError * __nullable error) {
       if (error != nil)
         return;
       MCOIMAPOperation * op = [session deleteFolderOperation:@"holidays 2009"]
       ...
     }];
*/
- (MCOIMAPOperation *) unsubscribeFolderOperation:(NSString *)folder;

3.13 copy

// 把一组信件复制到制定的信箱,保留他们的标志和内部信息
/**
 Returns an operation to copy messages to a folder.

     MCOIMAPCopyMessagesOperation * op = [session copyMessagesOperationWithFolder:@"INBOX"
                                                                             uids:[MCIndexSet indexSetWithIndex:456]
                                                                       destFolder:@"Cocoa"];
     [op start:^(NSError * __nullable error, NSDictionary * uidMapping) {
          NSLog(@"copied to folder with UID mapping %@", uidMapping);
     }];
*/
- (MCOIMAPCopyMessagesOperation *)copyMessagesOperationWithFolder:(NSString *)folder
                                                             uids:(MCOIndexSet *)uids
                                                       destFolder:(NSString *)destFolder NS_RETURNS_NOT_RETAINED;

3.14 check

// 允许客户机出发当前选择信箱的一个检查点

3.15 search

// 获取匹配的信件

/**
 Returns an operation to search for messages with a simple match.

     MCOIMAPSearchOperation * op = [session searchOperationWithFolder:@"INBOX"
                                                                 kind:MCOIMAPSearchKindFrom
                                                         searchString:@"laura"];
     [op start:^(NSError * __nullable error, MCOIndexSet * searchResult) {
          ...
     }];
*/
- (MCOIMAPSearchOperation *) searchOperationWithFolder:(NSString *)folder
                                                  kind:(MCOIMAPSearchKind)kind
                                          searchString:(NSString *)searchString;

/**

3.16 fetch

//获取邮箱的制定数据项
/** @name Fetching Messages */

/**
 Returns an operation to fetch messages by UID.

     MCOIMAPFetchMessagesOperation * op = [session fetchMessagesByUIDOperationWithFolder:@"INBOX"
                                                                             requestKind:MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure
                                                                                    uids:MCORangeMake(1, UINT64_MAX)];
     [op start:^(NSError * __nullable error, NSArray * messages, MCOIndexSet * vanishedMessages) {
        for(MCOIMAPMessage * msg in messages) {
          NSLog(@"%lu: %@", [msg uid], [msg header]);
        }
     }];
*/
- (MCOIMAPFetchMessagesOperation *) fetchMessagesByUIDOperationWithFolder:(NSString *)folder
                                                              requestKind:(MCOIMAPMessagesRequestKind)requestKind
                                                                     uids:(MCOIndexSet *)uids DEPRECATED_ATTRIBUTE;

3.17 store

// 更改制定新建组的信件标志
/**
 Returns an operation to change flags of messages.

 For example: Adds the seen flag to the message with UID 456.

     MCOIMAPOperation * op = [session storeFlagsOperationWithFolder:@"INBOX"
                                                               uids:[MCOIndexSet indexSetWithIndex:456]
                                                               kind:MCOIMAPStoreFlagsRequestKindAdd
                                                              flags:MCOMessageFlagSeen];
     [op start:^(NSError * __nullable error) {
          ...
     }];
*/
- (MCOIMAPOperation *) storeFlagsOperationWithFolder:(NSString *)folder
                                                uids:(MCOIndexSet *)uids
                                                kind:(MCOIMAPStoreFlagsRequestKind)kind
                                               flags:(MCOMessageFlag)flags;

3.18 expunge

//永久删除当前选择信箱中设置为删除标志的邮件
/**
 Returns an operation to expunge a folder.

     MCOIMAPOperation * op = [session expungeOperation:@"INBOX"];
     [op start:^(NSError * __nullable error) {
          ...
     }];
*/
- (MCOIMAPOperation *) expungeOperation:(NSString *)folder;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容