I m working on iPhone eBook app.
In my app books are created using HTML.
In Index.html page i have to put the email functionality which email(send) the contents of particular chapter.
Now by using webview i show the index.html and in that i have created UIActionSheet which will show the Email button.
Please suggest me that how can i identify the index of different links to send
email of particular chapter.
Below code will work even if you have not configured email in your device.
Here is the code:
- (IBAction) sendEmail:(id)sender
{
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil)
{
// We must always check whether the current device is configured for sending emails
if ([mailClass canSendMail])
{
[self displayComposerSheet];
}
else
{
[self launchMailAppOnDevice];
}
}
else
{
[self launchMailAppOnDevice];
}
}
-(void)displayComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Hello from DShah!"];
NSArray *toRecipients = [NSArray arrayWithObject:#"first#example.com"];
NSArray *ccRecipients = [NSArray arrayWithObjects:#"second#example.com", #"third#example.com", nil];
NSArray *bccRecipients = [NSArray arrayWithObject:#"fourth#example.com"];
[picker setToRecipients:toRecipients];
[picker setCcRecipients:ccRecipients];
[picker setBccRecipients:bccRecipients];
NSString *path = [[NSBundle mainBundle] pathForResource:#"userdata" ofType:#"abc"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.abc", #"userdata"]];
NSData *myData = [NSData dataWithContentsOfFile:fullPath];
[picker addAttachmentData:myData mimeType:#"csv" fileName:#"userdata.abc"];
NSString *emailBody = #"It is raining in sunny California!";
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
[picker release];
}
-(void)launchMailAppOnDevice
{
NSString *recipients = #"mailto:first#example.com&subject=Hello from DShah!";
NSString *body = #"&body=It is cold in Winter!";
NSString *email = [NSString stringWithFormat:#"%#%#", recipients, body];
email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}
Then implement the Delegate method as below....
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
switch (result)
{
case MFMailComposeResultCancelled:
message = #"Result: canceled";
break;
case MFMailComposeResultSaved:
message = #"Result: saved";
break;
case MFMailComposeResultSent:
message = #"Result: sent";
break;
case MFMailComposeResultFailed:
message = #"Result: failed";
break;
default:
message = #"Result: not sent";
break;
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Email Demo" message:message delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
[self dismissModalViewControllerAnimated:YES];
}
Check out Apple's MailComposer example. This will show you everything you need. http://developer.apple.com/library/ios/#samplecode/MailComposer/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008865
Related
i have to send html text to mail as an attachment with a pdf extension.
Code :
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
NSArray *toReceipents =[NSArray arrayWithObjects:#"", nil];
[mailViewController setToRecipients:toReceipents];
[mailViewController setSubject:strMailMessage];
NSLog(#"Mail Message:%# %#",strMailMessage,appDelegate.strShareText);
NSData* data = [appDelegate.strShareText dataUsingEncoding:NSUTF8StringEncoding];
[mailViewController setMessageBody:appDelegate.strShareText isHTML:YES];
[mailViewController addAttachmentData:data mimeType:#"application/pdf" fileName:#"Medication file.pdf"];
[self presentModalViewController:mailViewController animated:YES];
[mailViewController release];
Note:when i download the pdf file i am getting the same text.but i want to show the text in table format in pdf document
Good code but for HTML try this ;) :
- (IBAction)mailCompose:(id)sender {
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[mail setSubject:#"Hello World!"];
NSArray *toRecipients = [NSArray arrayWithObjects:#"e-mail here or leve empty", nil];
[mail setToRecipients:toRecipients];
NSString *emailBody = #"Body message App</b><br /><a href='https://itunes.apple.com/it/app/yourApp/id'>Download Free on AppStore!</a>";
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"myVoice.caf"];
NSData *myData = [NSData dataWithContentsOfFile:filePath];
[mail addAttachmentData:myData mimeType:documentsDirectory fileName:#"myVoice.caf"];
[mail setMessageBody:emailBody isHTML:YES];
mail.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentViewController:mail animated:YES completion:nil];
}
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
switch (result) {
case MFMailComposeResultCancelled:
NSLog(#"Cancelled");
break;
case MFMailComposeResultSaved:
NSLog(#"Saved");
break;
case MFMailComposeResultFailed:
NSLog(#"Faild");
break;
case MFMailComposeResultSent:
NSLog(#"Sent");
break;
default:
NSLog(#"Default");
break;
}
[self dismissViewControllerAnimated:YES completion:nil];
}
Enjy hope this can help you
My app is to create csv file and send it through mail. But when I discard mail, I'm getting black screen. The previous view is not appearing and is being covered by the black screen. I viewed various questions and answers in stack overflow. But nothing seems to be working.
- (IBAction)openMail:(id)sender
{
[self getdata];
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:#"BMNET- Travel Log"];
NSString *CSVstring=#"Name, StartingDateNTime, EndingDateNTime, TravelType, DistanceTravelled, Amount\n" ;
NSString *CSVPath,*record;;
NSString *temporayCSV= #"" ;
for (int i=0; i<[getAmount count]; i++) {
record = [NSString stringWithFormat:#"%#, %#, %#, %#, %#, %#", [getName objectAtIndex:i], [getStartDate objectAtIndex:i], [getEndDate objectAtIndex:i],[getType objectAtIndex:i],[getDistance objectAtIndex:i],[getAmount objectAtIndex:i]];
NSLog(#"%d",i);
temporayCSV = [NSString stringWithFormat:#"%d %# \n ",(i+1),record];
CSVstring = [CSVstring stringByAppendingFormat:temporayCSV];
NSLog(#"%#",CSVstring);
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *toRecipients = [NSArray arrayWithObjects:#"", nil];
[mailer setToRecipients:toRecipients];
CSVPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.csv", #"CSV_FormatedTable"]];
NSFileManager *fileManager;
//add our file to the path
[fileManager createFileAtPath:CSVPath contents:[CSVstring dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
NSData *rolesCSVData =[NSData dataWithContentsOfFile:CSVPath];
NSLog(#"The data is %#",CSVstring);
//create my data to append
NSFileHandle *handle;
handle = [NSFileHandle fileHandleForWritingAtPath: CSVPath ];
//say to handle where's the file fo write
[handle truncateFileAtOffset:[handle seekToEndOfFile]];
//position handle cursor to the end of file
[handle writeData:[data dataUsingEncoding:NSUTF8StringEncoding]];
//write data to with the right encoding
[mailer addAttachmentData:rolesCSVData mimeType:#"text/csv" fileName:#"Log"];
NSString *emailBody = #"Attachment of Log";
[mailer setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:mailer animated:YES];
mailer.modalPresentationStyle = UIModalPresentationPageSheet;
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Failure"
message:#"Your device doesn't support the composer sheet"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
- (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];
}
presentModalViewController:animated: and dismissModalViewControllerAnimated: are deprecated as of iOS6, just as a side note!
which iOS versions are you targeting for and is this a iPhone or iPad application you're working on?
beside that i noticed the following:
[self presentModalViewController:mailer animated:YES];
mailer.modalPresentationStyle = UIModalPresentationPageSheet;
you're setting the modalPresentationStyle after you've presented the view controller!
move the line mailer.modalPresentationStyle = UIModalPresentationPageSheet; before the presentModalViewController line. Maybe this is the problem!
I am writing an iPhone app that requires that I send an e-mail attachment programmatically. The attachment is a csv file, that I create through the code. I then attach the file to the email, and the attachment shows up on the phone. When I send the email to myself, however, the attachment doesn't appear in the e-mail. Here is the code I'm using.
[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];
The is being successfully created- I checked in the simulator files.
- (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);
}
try
[mailer addAttachmentData:myData mimeType:#"text/csv" fileName:#"expenses.csv"];
Edit:
This is the code I'm using in my app:
- (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];
}
Dani's answer is great, however the code seems to be too long for someone looking for a simple way to send an attachment through email programatically.
The Gist
I pruned his answer to take out only the important bits, as well as refactored it like so:
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];
That's basically the gist of it, this is enough as it is. If, for example, you put this code on a button's action, it will present an email composing screen with the respective fields pre-filled up, as well as having the file you want attached to the email.
Further Reading
Framework
The MFMailComposeViewController is under the MessageUI Framework, so to use it, import (if you have not done yet) the Framework like so:
#import <MessageUI/MessageUI.h>
Mail Capability Checking
Now when you run the source code, and you have not yet setup a mail account on your device, (not sure what the behavior is on simulator), this code will crash your app. It seems that if the mail account is not yet setup, doing [[MFMailComposeViewController alloc] init] will still result in the mailComposer being nil, causing the crash. As the answer in the linked question states:
You should check is MFMailComposeViewController are able to send your mail just before sending
You can do this by using the canSendMail method like so:
if (![MFMailComposeViewController canSendMail]) {
[self openCannotSendMailDialog];
return;
}
You can put this right before doing [[MFMailComposeViewController alloc] init] so that you can notify the user immediately.
Handling cannotSendMail
If canSendMail returns false, according to Apple Dev Docs, that means that the device is not configured for sending mail. This could mean that maybe the user has not yet setup their Mail account. To help the user with that, you can offer to open the Mail app and setup their account. You can do this like so:
NSURL *mailUrl = [NSURL URLWithString:#"message://"];
if ([[UIApplication sharedApplication] canOpenURL:mailUrl]) {
[[UIApplication sharedApplication] openURL:mailUrl];
}
You can then implement openCannotSendMailDialog like so:
- (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];
}
Mime Types
If like me, you forgot/are unsure which mimeType to use, here is a resource you can use. Most probably, text/plain is enough, if the file you are attaching is just a plain text, or image/jpeg / image/png for images.
Delegate
As you probably noticed, Xcode throws us a warning on the following line:
mailComposer.mailComposeDelegate = self;
This is because we have not yet set ourself to conform to the appropriate protocol and implement its delegate method. If you want to receive events whether the mail was cancelled, saved, sent or even failed sending, you need to set your class to conform to the protocol MFMailComposeViewControllerDelegate, and handle the following events:
MFMailComposeResultSent
MFMailComposeResultSaved
MFMailComposeResultCancelled
MFMailComposeResultFailed
According to Apple Dev Docs (emphasis mine):
The mail compose view controller is not dismissed automatically. When the user taps the buttons to send the email or cancel the interface, the mail compose view controller calls the mailComposeController:didFinishWithResult:error: method of its delegate. Your implementation of that method must dismiss the view controller explicitly.
With this in mind, we can then implement the delegate method like so:
- (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];
}
Conclusion
The final code may look like so:
- (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];
}
}];
}
With the button action looking like:
- (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"];
}
I kind of went overboard here, but you can, with a grain of salt, take and use the code I posted here. Of course there is a need to adapt it to your requirements, but that is up to you. (I also modified this answer from my working source code, so there might be errors somewhere, please do comment if you find one :))
The issue was that I wasn't looking in the proper place for the file. Thanks #EmilioPalesz .
Here's the code I needed:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *root = [documentsDir stringByAppendingPathComponent:#"expenses.csv"]
NSData *myData = [NSData dataWithContentsOfFile:root];
I'm in the process of using a plist to populate a uitableview. I was wondering, because one of my keys is email, what type would it be? Data, string, etc. The basic idea is to have a table, you tap the email cell, and up comes with the email modal view. How do i go about doing this?
Thanks
The data type I would use would be a string. You can then pull out this string and use it where you need it. In the case of email, you will need to do the following (I am assuming you are able to read the string out of the plist and use it within a UITableViewCell):
#pragma mark -
#pragma mark Compose Mail
-(void)callMailComposer
{
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil)
{
// We must always check whether the current device is configured for sending emails
if ([mailClass canSendMail])
{
[self displayComposerSheet];
}
else
{
[self launchMailAppOnDevice];
}
}
else
{
[self launchMailAppOnDevice];
}
}
// Displays an email composition interface inside the application. Populates all the Mail fields.
-(void)displayComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"My email subject"];
//Just an extra example if you were wanting to add an attachment :)
/* NSString* pdfFileName = #"pdf_file.pdf";
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:pdfFileName];
[picker addAttachmentData:[NSData dataWithContentsOfFile:documentDirectoryFilename] mimeType:#"application/pdf" fileName:pdfFileName]; */
// Set up recipients
[picker setCcRecipients:nil];
[picker setBccRecipients:nil];
[picker setToRecipients:[NSArray arrayWithObjects:#"myEmailAddressFromPlist",nil]];
NSString *emailBody = #"Hey you got mail";
[picker setMessageBody:emailBody isHTML:YES];
[self presentModalViewController:picker animated:YES];
[picker release];
picker=nil;
}
// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the message field with the result of the operation.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
NSString* alertMessage;
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
alertMessage = #"Email composition cancelled";
break;
case MFMailComposeResultSaved:
alertMessage = #"Your e-mail has been saved successfully";
break;
case MFMailComposeResultSent:
alertMessage = #"Your email has been sent successfully";
break;
case MFMailComposeResultFailed:
alertMessage = #"Failed to send email";
break;
default:
alertMessage = #"Email Not Sent";
break;
}
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:#"My application" message:alertMessage delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark Workaround
// Launches the Mail application on the device.
-(void)launchMailAppOnDevice
{
//You will need to fill these in
NSString *recipients = #"mailto:?cc=&subject=";
NSString *body = #"&body=";
NSString *email = [NSString stringWithFormat:#"%#%#", recipients, body];
email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}
I have send an attachment through iPhone application.
But when I see the mail, I can see the upin that shows that something is attached.
But when I open the mail I couldn't found any attachment?
What is the problem behind this?
-(IBAction)btnPressedExport:(id)sender{
NSArray *x=[[NSArray alloc] initWithArray:[DatabaseAccess getAllTransactionsForUserID:[BudgetTrackerAppDelegate getUserID] profileID:[BudgetTrackerAppDelegate getProfileID]]];
int i=-1,j=[x count];
NSDictionary *tmp;
NSMutableString *stringToWrite=[[NSMutableString alloc] init];
for(;i<j;i++){
if(i==-1){
[stringToWrite appendString:#"TransactionID,TransactionDate,ProfileName,ProfileType,GroupName,GroupType,CategoryName,TransactionAmt\n"];
} else {
tmp=[x objectAtIndex:i];
[stringToWrite appendFormat:#"%#,%#,%#,%#,%#,%#,%#,%#\n",
[tmp valueForKey:#"TraID"],[tmp valueForKey:#"TraDate"],[tmp valueForKey:#"ProfileName"],[tmp valueForKey:#"ProfileType"],[tmp valueForKey:#"GroupName"],[tmp valueForKey:#"GroupType"],[tmp valueForKey:#"CatName"],[tmp valueForKey:#"TraAmt"]];
}
}
[stringToWrite writeToFile:[self pathOfCSVForExport] atomically:YES encoding:NSStringEncodingConversionAllowLossy error:nil];
// [stringToWrite writeToFile:[self pathOfCSVForExport] atomically:YES];
picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate=self;
// picker.delegate=self;
[picker setSubject:#"Hello from Sugar!"];
//Set up recipients
NSArray *toRecipients = [NSArray arrayWithObject:#"sugar.srk#pqr.com"];
// NSArray *ccRecipients = [NSArray arrayWithObjects:#"xyz.dalal#pqr.com", #"kandarp.dave#phptalent.com", nil];
// NSArray *bccRecipients = [NSArray arrayWithObject:#"fourth#example.com"];
[picker setToRecipients:toRecipients];
[picker setCcRecipients:ccRecipients];
// [picker setBccRecipients:bccRecipients];
// Attach an image to the email
NSString *path = [[NSBundle mainBundle] pathForResource:#"myExport" ofType:#"csv"];
NSData *myData = [NSData dataWithContentsOfFile:path];
NSString *fileNameToSend=#"BudgetTracker.csv";//[NSString stringWithFormat:#"%#.csv",[x valueForKey:#"ProfileName"]];
[picker addAttachmentData:myData mimeType:#"text/plain" fileName:fileNameToSend];
// text/html/
// Fill out the email body text
NSString *emailBody = [NSString stringWithFormat:#"%#",#"Hello! This is export test."];
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
}
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
// NSLog(#"here2");
switch (result)
{
case MFMailComposeResultCancelled: break;
case MFMailComposeResultSaved: break;
case MFMailComposeResultSent: break;
case MFMailComposeResultFailed: break;
default: break;
}
// self.navigationController.navigationBarHidden=NO;
// [self becomeFirstResponder];
[self dismissModalViewControllerAnimated:YES];
}
This looks wrong, unless it's just for testing:
// Attach an image to the email
NSString *path = [[NSBundle mainBundle] pathForResource:#"myExport" ofType:#"csv"];
NSData *myData = [NSData dataWithContentsOfFile:path];
the path you're using is to a file in your application bundle, which is read-only, so it can't be the CSV file you just made.
if you want to write a temporary file and email it, you need to write it to someplace like your Documents directory, i.e. a path like
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *docDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/myexport.csv", docDirectory];