使用MailCore创建iOS邮件客户端(一)

 大部分邮箱支持标准的邮件收发协议,比如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服务器界面:

使用MailCore创建iOS邮件客户端(一)_第1张图片


代码: CTCoreAccount *account = openconnect ();openconnect()函数使用UserDefaults中保存的帐号、密码和服务器URL来登录imap服务器。由于邮件服务器的登录是一项经常性的工作(因为网络超时或3G信号不稳定等原因,经常会导致服务器连接丢失),所以我们把登录动作实现为一个公共函数,具体实现如下:

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显示出所有邮箱文件夹,如图所示:

使用MailCore创建iOS邮件客户端(一)_第2张图片

当点击某个邮箱文件夹,我们列出文件夹内的邮件列表。

你可能感兴趣的:(使用MailCore创建iOS邮件客户端(一))