读书人

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

发布时间: 2012-12-22 12:05:06 作者: rapoo

使用MailCore创建iOS邮件客户端(二)
三、列出邮件列表

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

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

代码如下:

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显示:

应用MailCore创建iOS邮件客户端(二)根据指定的文件夹路径和邮件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

[selfextractAttachmentsFromMessage: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了。

读书人网 >操作系统

热点推荐