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

三、列出邮件列表

列出某个文件夹路径(folderPath)下的所有邮件列表,如下图所示:

代码如下:

CTCoreAccount* acc=UIAppDelegate.account;

    if (!acc || ![acc isConnected]) {

        NSLog(@"连接丢失,重新连接IMAP服务器!");

        acc=openconnect();

    }

    CTCoreFolder *folder = [acc folderWithPath: folderPath];

    messages=[[NSArrayalloc]initWithArray:[folder messagesFromSequenceNumber:1to:0 withFetchAttributes:CTFetchAttrEnvelope]];// |

    [tbMailListreloadData]; 首先需要检测连接是否丢失,如果丢失进行重连(这需要用到帐号、密码等信息,这些东西我们保存在UserDefaults中)。然后用folderPath初始化CTCoreFolder对象。并调用CTCoreFolder对象的messagesFromSequenceNumber:withFetchAttributes:方法。这个方法会去抓取服务器上的邮件信息,我们在《 MailCore 快速入门指南》中进行过介绍。关键是第二个参数指定了抓取选项,即一个 CTFetchAttributes 枚举参数。如果抓取选项为CTFetchAttrEnvelope,则指定了我们要读取的仅仅是邮件的信封,因为信封中包含from、to、subject、sentDate等信息——这些信息我们会在UITableview的单元格中列出,但不会抓取正文信息。如果要读取正文,需要使用CTFetchAttrBodyStructure选项。还有一种选项,是CTFetchAttrDefaultsOnly,仅抓取邮件的编号(UID)和大小。这三种选项可以进行“|”(或)运算,比如正文和信封一起抓取。

四、列出邮件正文

邮件正文可以用一个WebView显示:

根据指定的文件夹路径和邮件UID,我们可以载入邮件正文。代码如下:

-(void)loadMsgFromUID:(int)UID folderPath:(NSString*)path{ CTCoreAccount* acc=UIAppDelegate.account;

⋯⋯

    CTCoreFolder* folder=[acc folderWithPath:path];

    CTCoreMessage* msg=[[folder messageWithUID:UID]retain];// CTCoreMessage  instancemust to be retain,otherwise crashed

    assert(msg);

    CTCoreAddress* from=[[msg from]anyObject];

    assert(from);

    NSString* sender=[from name];// just one CTCoreAddress in the from set

    CGSize constraint = CGSizeMake(206, 21);

   

    CGSize size = [sender sizeWithFont:[UIFontsystemFontOfSize:10]constrainedToSize:constraint lineBreakMode:UILineBreakModeTailTruncation];

    [lbSendersetText:sender];

    [lbSendersetFrame:CGRectMake(lbSender.frame.origin.x, lbSender.frame.origin.y, MAX(size.width, 40), 21)];

    [btSendersetFrame:lbSender.frame];

    // Subject

    lbSubject.text=[msg subject];

    // Sent Date

    NSDate* date=[msg sentDateGMT];

    if(date == nil) {

        // if you couldn't get the sent date from the message, use a fake datein the distant past

        date = [NSDatedistantPast];

    }

    NSDateFormatter*df=[[NSDateFormatteralloc]init];

    df.dateFormat=@"yyyy-MM-dd HH:mm";

    lbSentDate.text=[df stringFromDate:date];

    [df release];

    // Body

    [wbBodyloadHTMLString:[selfextractBodyFromMessage:msg]

                  baseURL:nil];

    // Attachments

    [ self extractAttachmentsFromMessage :msg]; }第2句的retain用的比较奇怪,也不需要你release。但你必须这样做,否则程序会崩溃,估计是MailCore的一个内存泄露。接下来一些代码是计算from按钮的Size——根据文字长度自动计算按钮size。最后调用extractBodyFromMessage:方法得到邮件正文载入到webview中,调用extractAttachmentsFromMessage:方法下载附件。这是extractBodyFromMessage:方法:

-(NSString*)extractBodyFromMessage:(CTCoreMessage*)msg{

    BOOL isHtml;

    NSString* body=[msg bodyPreferringPlainText:&isHtml];

//   NSLog(@"body:%@",[msg body]);

    NSString* keyString=@"【来自网易邮箱的超大附件】";

    NSScanner* scanner=[NSScannerscannerWithString:body];

    [scanner setCaseSensitive:NO];

//   NSCharacterSet *kippedSet=[NSCharacterSetcharacterSetWithCharactersInString:@""];

//    [scannersetCharactersToBeSkipped:kippedSet];

    BOOL b;

    while (![scanner isAtEnd]) {

        b=[scanner scanString:keyString intoString:NULL];

        if (b) {

           body=[body substringToIndex:[scanner scanLocation]-keyString.length];

            break;

        }else{

            scanner.scanLocation++;

        }

    }

    return body;

}这个方法主要是过滤掉文本中的多余字符。比如126邮箱,会在邮件正文后面加上附件下载和预览的链接。如果是text/plain类型的附件,还会把附件文本加在正文最后。因此我们查找邮件正文文本,把“ 【来自网易邮箱的超大附件】”之后的部分统统截去。这是 extractAttachmentsFromMessage 方法:

-(void)extractAttachmentsFromMessage:(CTCoreMessage*)msg{

    NSArray *atts=[msg attachments];

    [attachmentsremoveAllObjects];

    for (CTBareAttachment* att in atts) {

        CTCoreAccount* acc=UIAppDelegate.account;

        if (!acc || ![acc isConnected]) {

            NSLog(@"连接丢失,重新连接IMAP服务器!");

            acc=openconnect();

        }

        CTCoreAttachment*core_att=[att fetchFullAttachment];

        core_att.charset=att.charset;

        assert(core_att);

        [attachmentsaddObject:core_att];

    }

}这个方法主要是调用CTCoreAttachment的fetchFullAttachment方法从服务器抓取附件,并把它放到一个NSMutableArray中(一个邮件可能有多个附件)。注意代码中core_att.charset=att.charset;一行你可能要注释掉。CTCoreAttachment并没有charset这个属性。我在这里使用是因为我修改了MailCore中的源代码。还有一个值得注意的是webview的委托方法:

- (void)webViewDidFinishLoad:(UIWebView *)webView{

    float offsetY=0;

    CGSize actualSize = [webView sizeThatFits:CGSizeZero];

   

    CGRect newFrame = webView.frame;

    newFrame.size.height = actualSize.height;

    webView.frame = newFrame;

    offsetY=newFrame.origin.y+newFrame.size.height;

    lbAttachmentsCount.frame=CGRectMake(lbAttachmentsCount.frame.origin.x,

                                       offsetY,

                                       lbAttachmentsCount.frame.size.width,

                                       lbAttachmentsCount.frame.size.height);

    lbAttachmentsCount.text=[NSStringstringWithFormat:@"共有 %d 个附件:",attachments.count];

    offsetY+=lbAttachmentsCount.frame.size.height;

    int i=0;

    for (CTCoreAttachment*att inattachments) {

        offsetY+=8;

        CGRect rect=CGRectMake(20,0,280, 37);

        UIButton* btn=[UIButtonbuttonWithType:UIButtonTypeRoundedRect];

        [btn setTitle:[att decodedFilename] forState:UIControlStateNormal];

        btn.frame=CGRectMake(rect.origin.x, offsetY, rect.size.width, rect.size.height);

        btn.tag=(NSInteger)att;

        [btn addTarget:selfaction:@selector(btnAttachClick:) forControlEvents:UIControlEventTouchUpInside];

        [scrollViewaddSubview:btn];

        offsetY+=rect.size.height;

        i++;

    }

    scrollView.contentSize=CGSizeMake(scrollView.contentSize.width,

                                     offsetY);

}当webview加载完正文,我们需要根据附件的数目在webview下面添加多个附件按钮(UIButton),并及时调整webview和scrollview的size。根据webview加载的内容,我们通过 sizeThatFits 方法即可获得html内容加载完成后,webview实际的 size。至于添加完附件载按钮后,我们只有用代码重新计算scrollview的contentsize了。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值