以编程方式通过电子邮件发送iphone附件

cod*_*der 7 email iphone

我正在编写一个iPhone应用程序,要求我以编程方式发送电子邮件附件.附件是一个csv文件,我通过代码创建.然后我将文件附加到电子邮件中,附件显示在手机上.但是,当我向自己发送电子邮件时,附件不会出现在电子邮件中.这是我正在使用的代码.

    [self exportData];

if ([MFMailComposeViewController canSendMail])
{
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"expenses" ofType:@"csv"];  
    NSData *myData = [NSData dataWithContentsOfFile:filePath]; 

    MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];

    mailer.mailComposeDelegate = self;

    [mailer setSubject:@"Vehicle Expenses from myConsultant"];

    NSString *emailBody = @"";
    [mailer setMessageBody:emailBody isHTML:NO];

    [mailer addAttachmentData:myData mimeType:@"text/plain" fileName:@"expenses"];

    [self presentModalViewController:mailer animated:YES];

    [mailer release]; 
}
else
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failure"
                                                    message:@"Your device doesn't support the composer sheet"
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];
}
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    switch (result)
    {
        case MFMailComposeResultCancelled:
            NSLog(@"Mail cancelled: you cancelled the operation and no email message was queued.");
            break;
        case MFMailComposeResultSaved:
            NSLog(@"Mail saved: you saved the email message in the drafts folder.");
            break;
        case MFMailComposeResultSent:
            NSLog(@"Mail send: the email message is queued in the outbox. It is ready to send.");
            break;
        case MFMailComposeResultFailed:
            NSLog(@"Mail failed: the email message was not saved or queued, possibly due to an error.");
        break;
        default:
            NSLog(@"Mail not sent.");
        break;
}

// Remove the mail view
[self dismissModalViewControllerAnimated:YES];
Run Code Online (Sandbox Code Playgroud)

正在成功创建 - 我检查了模拟器文件.

- (void) exportData
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES); 
    NSString *documentsDir = [paths objectAtIndex:0];
    NSString *root = [documentsDir stringByAppendingPathComponent:@"expenses.csv"];
    NSString *temp=@"Date,Purpose,Start Odometer,End Odometer, Total Driven, Fees, ";
    for(int i = 0; i < expenses.count; i++){
        VehicleExpense *tempExpense = [expenses objectAtIndex:i];
        temp = [temp stringByAppendingString:tempExpense.date];
        temp = [temp stringByAppendingString:@", "];
        temp = [temp stringByAppendingString:tempExpense.purpose];
        temp = [temp stringByAppendingString:@", "];
        temp = [temp stringByAppendingString:[NSString stringWithFormat: @"%.02f",tempExpense.start_mile]];
        temp = [temp stringByAppendingString:@", "];
        temp = [temp stringByAppendingString:[NSString stringWithFormat: @"%.02f",tempExpense.end_mile]];
        temp = [temp stringByAppendingString:@", "];
        temp = [temp stringByAppendingString:[NSString stringWithFormat: @"%.02f",tempExpense.distance]];
        temp = [temp stringByAppendingString:@", "];
        temp = [temp stringByAppendingString:[NSString stringWithFormat: @"%.02f",tempExpense.fees]];
        temp = [temp stringByAppendingString:@", "];
    }
    [temp writeToFile:root atomically:YES encoding:NSUTF8StringEncoding error:NULL];
    NSLog(@"got here in export data--- %@", documentsDir);

}
Run Code Online (Sandbox Code Playgroud)

Dan*_*lea 11

尝试 [mailer addAttachmentData:myData mimeType:@"text/csv" fileName:@"expenses.csv"];

编辑: 这是我在我的应用中使用的代码:

- (IBAction) ExportData:(id)sender
{       
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:kExportFileName];

    self.timeRecords = [[NSMutableArray alloc] init];
    for (int i=0; i< [self.selectedTimeEntries count]; i++) 
        for (int j=0; j<[[self.selectedTimeEntries objectAtIndex:i] count]; j++) 
            if ([[self.selectedTimeEntries objectAtIndex:i] objectAtIndex:j] == [NSNumber numberWithBool:YES]) 
                [self.timeRecords addObject:[self timeEntriesForDay:[self.uniqueArray objectAtIndex:i] forIndex:j]];

    if( !([self.timeRecords count]!=0))
    {
        UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"There are no time entries selected!" message:@"Please select at least one time entry before proceeding" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        [alert release];        
        return;
    }
    NSMutableString *csvLine;
    NSError *err = nil;
    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd"];
    NSString *dateString = nil;
    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setPositiveFormat:@"###0.##"];
    NSString *formattedNumberString = nil;

    if(![[NSFileManager defaultManager] fileExistsAtPath:filePath])        
    {
        [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
    }

    for (timeEntries *timeEntry in self.timeRecords) {
        csvLine = [NSMutableString stringWithString:timeEntry.client];
        [csvLine appendString:@","];
        [csvLine appendString:timeEntry.category];
        [csvLine appendString:@","];
        [csvLine appendString:timeEntry.task];
        [csvLine appendString:@","];
        dateString = [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:timeEntry.date]];
        [csvLine appendString:dateString];
        [csvLine appendString:@","];
        formattedNumberString = [numberFormatter stringFromNumber:timeEntry.duration];
        [csvLine appendString:formattedNumberString];
        [csvLine appendString:@","];
        [csvLine appendString:timeEntry.description];
        [csvLine appendString:@"\n"];

        if([[NSFileManager defaultManager] fileExistsAtPath:filePath])        
        {     
            NSString *oldFile = [[NSString alloc] initWithContentsOfFile:filePath];
            [csvLine insertString:oldFile atIndex:0];
            BOOL success =[csvLine writeToFile:filePath atomically:NO encoding:NSUTF8StringEncoding error:&err];
            if(success){

            }
            [oldFile release];
        }
    } 
    if (!appDelegate.shouldSendCSV) {
    self.csvText = csvLine;
    }
    if([[NSFileManager defaultManager] fileExistsAtPath:filePath])        
    {
        [self emailExport:filePath];
    }   
    self.selectedTimeEntries =nil;
    self.navigationController.toolbarHidden = NO;
}


- (void)emailExport:(NSString *)filePath
{
    NSLog(@"Should send CSV = %@", [NSNumber numberWithBool:appDelegate.shouldSendCSV]);
    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
    picker.mailComposeDelegate = self;

    // Set the subject of email
    [picker setSubject:@"My Billed Time Export"];

    // Add email addresses
    // Notice three sections: "to" "cc" and "bcc"   

    NSString *valueForEmail = [[NSUserDefaults standardUserDefaults] stringForKey:@"emailEntry"];
    NSString *valueForCCEmail = [[NSUserDefaults standardUserDefaults] stringForKey:@"ccEmailEntry"];
    if( valueForEmail == nil ||  [valueForEmail isEqualToString:@""])
    {
        UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"Please set an email address before sending a time entry!" message:@"You can change this address later from the settings menu of the application!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        [alert release];        

        return;
    }
    else {
        [picker setToRecipients:[NSArray arrayWithObjects:valueForEmail, nil]];
    }

    if(valueForCCEmail != nil || ![valueForCCEmail isEqualToString:@""])
    {
        [picker setCcRecipients:[NSArray arrayWithObjects:valueForCCEmail, nil]];
    }

    // Fill out the email body text
    NSString *emailBody = @"My Billed Time Export File.";

    // This is not an HTML formatted email
    [picker setMessageBody:emailBody isHTML:NO];

    if (appDelegate.shouldSendCSV) {

    // Create NSData object from file
    NSData *exportFileData = [NSData dataWithContentsOfFile:filePath];

    // Attach image data to the email 
    [picker addAttachmentData:exportFileData mimeType:@"text/csv" fileName:@"MyFile.csv"];
    } else {
        [picker setMessageBody:self.csvText isHTML:NO];
    }
    // Show email view  
    [self presentModalViewController:picker animated:YES];

    // Release picker
    [picker release];
}
Run Code Online (Sandbox Code Playgroud)


Kea*_*ale 5

Dani答案很好,但是对于寻找通过电子邮件以编程方式发送附件的简单方法的人来说,代码似乎太长了

要旨

我修剪了他的答案,只删除重要的部分,并像这样重构它:

MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];
mailComposer.mailComposeDelegate = self;

mailComposer.subject = @"Sample subject";

mailComposer.toRecipients = @[@"arthur@example.com", @"jeanne@example.com", ...];
mailComposer.ccRecipients = @[@"nero@example.com", @"mashu@example.com", ...];

[mailComposer setMessageBody:@"Sample body" isHTML:NO];

NSData *fileData = [NSData dataWithContentsOfFile:filePath];
[mailComposer addAttachmentData:fileData
                       mimeType:mimeType
                       fileName:fileName];

[self presentViewController:mailComposer animated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)

基本上这就是要点,这样就足够了。例如,如果您将此代码放在按钮的操作上,它将显示一个电子邮件撰写屏幕,其中预先填写了相应的字段,以及您想要附加到电子邮件的文件。

进一步阅读

框架

MFMailComposeViewController位于MessageUI框架下,因此要使用它,请导入(如果尚未完成)框架,如下所示:

#import <MessageUI/MessageUI.h>
Run Code Online (Sandbox Code Playgroud)

邮件能力检查

现在,当您运行源代码,并且尚未在设备上设置邮件帐户(不确定模拟器上的行为是什么)时,此代码将使您的应用程序崩溃。看来如果邮件账户还没有设置的话,还是[[MFMailComposeViewController alloc] init]会导致mailComposernil,导致崩溃。作为答案链接问题中的

您应该在发送之前检查 MFMailComposeViewController 是否能够发送您的邮件

您可以使用canSendMail方法来执行此操作,如下所示:

if (![MFMailComposeViewController canSendMail]) {
    [self openCannotSendMailDialog];
    return;
}
Run Code Online (Sandbox Code Playgroud)

您可以在执行此操作之前将其放在正确位置[[MFMailComposeViewController alloc] init],以便可以立即通知用户。

处理cannotSendMail

根据 Apple Dev 文档,如果canSendMail返回 false,则意味着该设备未配置为发送邮件。这可能意味着用户可能尚未设置其邮件帐户。为了帮助用户完成此操作,您可以打开邮件应用程序并设置他们的帐户。你可以这样做:

NSURL *mailUrl = [NSURL URLWithString:@"message://"];
if ([[UIApplication sharedApplication] canOpenURL:mailUrl]) {
    [[UIApplication sharedApplication] openURL:mailUrl];
}
Run Code Online (Sandbox Code Playgroud)

openCannotSendMailDialog然后你可以像这样实现:

- (void)openCannotSendMailDialog
{
    UIAlertController *alert =
        [UIAlertController alertControllerWithTitle:@"Error"
                                            message:@"Cannot send mail."
                                preferredStyle:UIAlertControllerStyleAlert];
        
    NSURL *mailUrl = [NSURL URLWithString:@"message://"];
    if ([[UIApplication sharedApplication] canOpenURL:mailUrl]) {
        [alert addAction:
         [UIAlertAction actionWithTitle:@"Open Mail"
                                  style:UIAlertActionStyleDefault
                                handler:^(UIAlertAction * _Nonnull action) {
            [[UIApplication sharedApplication] openURL:mailUrl];
        }]];
        
        [alert addAction:
         [UIAlertAction actionWithTitle:@"Cancel"
                                  style:UIAlertActionStyleCancel
                                handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        
    } else {
        [alert addAction:
         [UIAlertAction actionWithTitle:@"OK"
                                  style:UIAlertActionStyleCancel
                                handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        
    }
        
    [self presentViewController:alert animated:YES completion:nil];
}
Run Code Online (Sandbox Code Playgroud)

哑剧类型

如果像我一样,您忘记/不确定mimeType使用哪个,这里是您可以使用的资源。text/plain如果您附加的文件只是纯文本或image/jpeg/image/png图像,很可能就足够了。

代表

您可能已经注意到,Xcode 在以下行中向我们发出警告:

mailComposer.mailComposeDelegate = self; 
Run Code Online (Sandbox Code Playgroud)

这是因为我们还没有让自己遵守适当的协议并实现其委托方法。如果你想接收邮件被取消、保存、发送甚至发送失败的事件,你需要设置你的类符合协议MFMailComposeViewControllerDelegate,并处理以下事件

  • MFMail撰写结果已发送
  • MFMailCompose结果已保存
  • MFMailComposeResultCancelled
  • MFMailComposeResult失败

根据苹果开发文档(强调我的):

邮件撰写视图控制器不会自动关闭。当用户点击按钮发送电子邮件或取消界面时,邮件撰写视图控制器会调用其委托的mailComposeController:didFinishWithResult:error:方法。该方法的实现必须明确地关闭视图控制器

考虑到这一点,我们可以像这样实现委托方法:

- (void)mailComposeController:(MFMailComposeViewController *)controller
          didFinishWithResult:(MFMailComposeResult)result
                        error:(NSError *)error
{
    switch (result) {
        case MFMailComposeResultSent:
            // Mail was sent
            break;
        case MFMailComposeResultSaved:
            // Mail was saved as draft
            break;
        case MFMailComposeResultCancelled:
            // Mail composition was cancelled
            break;
        case MFMailComposeResultFailed:
            // 
            break;
        default:
            // 
            break;
    }
    
    // Dismiss the mail compose view controller.
    [controller dismissViewControllerAnimated:YES completion:nil];
}
Run Code Online (Sandbox Code Playgroud)

结论

最终代码可能如下所示:

- (void)openMailComposerWithSubject:(NSString *)subject
                   toRecipientArray:(NSArray *)toRecipientArray
                   ccRecipientArray:(NSArray *)ccRecipientArray
                        messageBody:(NSString *)messageBody
                  isMessageBodyHTML:(BOOL)isHTML
                attachingFileOnPath:(NSString)filePath
                           mimeType:(NSString *)mimeType
{
    if (![MFMailComposeViewController canSendMail]) {
        [self openCannotSendMailDialog];
        return;
    }

    MFMailComposeViewController *mailComposer = 
        [[MFMailComposeViewController alloc] init];
    mailComposer.mailComposeDelegate = self;
    
    mailComposer.subject = subject;
    
    mailComposer.toRecipients = toRecipientArray;
    mailComposer.ccRecipients = ccRecipientArray;
    
    [mailComposer setMessageBody:messageBody isHTML:isHTML];
    
    NSData *fileData = [NSData dataWithContentsOfFile:filePath];
    NSString *fileName = filePath.lastPathComponent;
    [mailComposer addAttachmentData:fileData
                           mimeType:mimeType
                           fileName:fileName];
    
    [self presentViewController:mailComposer animated:YES completion:nil];
}

- (void)openCannotSendMailDialog
{
    UIAlertController *alert =
        [UIAlertController alertControllerWithTitle:@"Error"
                                            message:@"Cannot send mail."
                                preferredStyle:UIAlertControllerStyleAlert];
    
    NSURL *mailUrl = [NSURL URLWithString:@"message://"];
    if ([[UIApplication sharedApplication] canOpenURL:mailUrl]) {
        [alert addAction:
         [UIAlertAction actionWithTitle:@"Open Mail"
                                  style:UIAlertActionStyleDefault
                                handler:^(UIAlertAction * _Nonnull action) {
            [[UIApplication sharedApplication] openURL:mailUrl];
        }]];
        
        [alert addAction:
         [UIAlertAction actionWithTitle:@"Cancel"
                                  style:UIAlertActionStyleCancel
                                handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        
    } else {
        [alert addAction:
         [UIAlertAction actionWithTitle:@"OK"
                                  style:UIAlertActionStyleCancel
                                handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        
    }
        
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)mailComposeController:(MFMailComposeViewController *)controller
          didFinishWithResult:(MFMailComposeResult)result
                        error:(NSError *)error
{
    NSString *message;
    switch (result) {
        case MFMailComposeResultSent:
            message = @"Mail was sent.";
            break;
        case MFMailComposeResultSaved:
            message = @"Mail was saved as draft.";
            break;
        case MFMailComposeResultCancelled:
            message = @"Mail composition was cancelled.";
            break;
        case MFMailComposeResultFailed:
            message = @"Mail sending failed.";
            break;
        default:
            // 
            break;
    }

    // Dismiss the mail compose view controller.
    [controller dismissViewControllerAnimated:YES completion:^{
        if (message) {
            UIAlertController *alert =
                [UIAlertController alertControllerWithTitle:@"Confirmation"
                                                    message:message
                                        preferredStyle:UIAlertControllerStyleAlert];
    
            [alert addAction:
             [UIAlertAction actionWithTitle:@"OK"
                                      style:UIAlertActionStyleCancel
                                    handler:^(UIAlertAction * _Nonnull action) {
                
            }]];

            [self presentViewController:alert animated:YES completion:nil];
        }
    }];
}
Run Code Online (Sandbox Code Playgroud)

按钮操作如下所示:

- (IBAction)mailButtonTapped:(id)sender
{
    NSString *reportFilePath = ...
    [self openMailComposerWithSubject:@"Report Files"
                     toRecipientArray:mainReportRecipientArray
                     ccRecipientArray:subReportRecipientArray
                          messageBody:@"I have attached report files in this email"
                    isMessageBodyHTML:NO
                  attachingFileOnPath:reportFilePath
                             mimeType:@"text/plain"];       
}
Run Code Online (Sandbox Code Playgroud)

我在这里有点太过分了,但是您可以持保留态度,接受并使用我在这里发布的代码。当然,需要根据您的要求进行调整,但这取决于您。(我还从我的工作源代码中修改了这个答案,因此某些地方可能有错误,如果您发现错误,请发表评论:))