列出某个文件夹路径(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了。