大部分邮箱支持标准的邮件收发协议,比如POP3、IMAP和SMTP。本教程以IMAP 为例,教你如何利用MailCore框架创建自己的iOS邮件客户端。
邮件客户端一般会包含收、发邮件两个功能。相对于发送邮件,接收邮件要复杂得多。本文采用IMAP协议实现邮件的接收,正如Mail程序所做的一样。
对于邮件发送,要容易得多,哪怕你不用MailCore框架,仅仅使用SDK内置的MessageUIframework也可以实现邮件的发送。
本文是MailCore框架系列的一部分,因时间关系,没有涉及邮件的发送——虽然MailCore本身仍然支持SMTP,但使用SDK内置功能发送邮件要更加简单一些。关于后者,你可以参考下面链接的文章:
http://mobile.tutsplus.com/tutorials/iphone/mfmailcomposeviewcontroller/
一、在项目中加入MailCore框架
这部分内容请参考作者其他篇、博文《 在项目中使用MailCore 》或者《 从reMail中获取MailCore框架》。二、连接imap服务器界面:CTCoreAccount* openconnect(){
TestPrefs* pref=[TestPrefssharedTestPrefs];
CTCoreAccount *account = [[CTCoreAccountalloc] init];
// NSLog(@"pref:%@,%d,%@,%@",pref.server,pref.port,pref.account,pref.password);
[account connectToServer:pref.server
port:pref.portconnectionType:CONNECTION_TYPE_PLAIN
authType:IMAP_AUTH_TYPE_PLAINlogin:pref.account
password:pref.password];
UIAppDelegate.account=account;
return account;
}注意,UIAppDelegate是一个宏,实际上指向[UIApplicationsharedApplication ].delegate。我们在AppDelegate中声明了一个account属性,这样account就变成了一个全局的CTCoreAccount对象,方便我们在任何地方使用。在登录界面中,如果登录成功,我们跳转到另一个邮箱文件夹视图。 二、列出所有文件夹 列出邮箱指定帐号下的所有文件夹很简单: NSSet *folders = [account allFolders ];这个Set中存放的是NSString对象,代表了一个文件夹的path(路径)。这个path对象可能是UTF7(一种ASCII编码)编码的——尤其是对于使用中文文件夹的126邮箱来说)。我们必须对他进行转换,以便显示正确的文件夹名称(UTF16编码):-(NSString*)imapFolderNameToDisplayName:(NSString*)folderPath {
if([folderPath isEqualToString:@"INBOX"]) {
return@"收件箱"; // TODO(gabor): Localize name
}
NSLog( @"Folder Path: %@", folderPath);
if(![StringUtilstringContains:folderPathsubString:@"&"]) {
return folderPath;
}
NSString* display = imapUTF7Decode( folderPath);
NSLog(@"Final: %@",display);
return display;
}这个方法调用了imapUTF7Decode函数进行字符UTF7-->UTF16转换:NSString* imapUTF7Decode(NSString* in)
{
// UTF7 is an all-ASCII format, bydesign
constchar *inBuf = [incStringUsingEncoding: NSASCIIStringEncoding];
size_t inLength = inBuf ? strlen( inBuf ) : 0;
// outBuf needs to beUTF-16 (so twice inLength). actual characters in
// outBuf may beshorter than inBuf characters, because of the 4::3 decoding
unsignedchar *outBuf = (unsignedchar*)malloc( 2*inLength );
NSString *out;
unsignedchar accumulated[BASE64_UNIT_SIZE]; // block of chars to translate at once
unsignedchar cur; // most recent BASE64 char to decode
unsignedchar decode; // decoded single BASE64 char value
size_t from = 0; // index into inBuf. goes up toinLength
size_t to = 0; // index into outBuf. Always less thaninLength
size_t i = 0; //index into accumulated
int accumulating = 0;
int timeToAdd = 0;
if ( !outBuf ) {
NSLog( @"Unable to allocate memory fordecoded string or unknown encoding of input data: %p:%@", inBuf, in );
returnin; // best optionavailable? unique,maybe-recognizable string
}
memset( accumulated, 0, sizeof accumulated );
while ( from < inLength ) // could do pointerarithmetic through this...
{
cur = inBuf[from++];
if ( cur == '&' )
{
accumulating = 1;
// don't add thischaracter
}
elseif ( !accumulating )
{
// not accumulating, just copy the character
outBuf[to++] = 0;
outBuf[to++] = cur;
}
else
{
if ( cur == '-' )
{
// end of block
accumulating = 0;
if ( i == 0 ) // only character
{
outBuf[to++] = 0;
/* kmyhy:eat the char'&' */
// outBuf[to++] = '&';
}
else
{
timeToAdd = 1;
}
}
else
{
decode = base64DecodeLookup[cur];
if ( decode == xx )
{
// skip over invalid characters, like linefeeds,etc.
//needed for general BASE64, but probably not this case
NSLog( @"Unexpected character in UTF-7:%c",cur );
}
else
{
accumulated[i++] = decode;
if ( i >= BASE64_UNIT_SIZE )
{
timeToAdd = 1;
}
}
}
if ( timeToAdd )
{
timeToAdd = 0;
to += addDecodedCharacters( outBuf, to,accumulated, i );
memset( accumulated, 0, sizeof accumulated );
i = 0;
}
}
}
if ( accumulating && i )
{
to+= addDecodedCharacters( outBuf, to,accumulated, i );
}
// if all went well, we now have a UTF16Big-Endian string.
out = [[NSStringalloc]
initWithBytes: outBuf
length: to
encoding:NSUTF16BigEndianStringEncoding];
free( outBuf );
returnout;
}用一个UITableView显示出所有邮箱文件夹,如图所示: 当点击某个邮箱文件夹,我们列出文件夹内的邮件列表。