I am trying to attach a video to an email. It is not a local video so I write it to a file. Then I get the data from that file and attach to the email. When the email comes up, the only thing there is the file name "video.mp4" with no video.
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
NSData *videoData = [NSData dataWithContentsOfURL:url];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *tempPath = [documentsDirectory stringByAppendingFormat:#"/video.mp4"];
NSLog(#"writing");
BOOL success = [videoData writeToFile:tempPath atomically:NO];
if (success){
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfFile:tempPath];
NSLog(#"path: %#", tempPath);
if (error) {
NSLog(#"%#", [error localizedDescription]);
}else{
[controller addAttachmentData:data mimeType:#"video/mp4" fileName:#"video.mp4"];
NSLog(#"Data has loaded successfully.");
}
}
I think only approach to try is formatting mail as HTML. Otherwise you will always sending an attachment.
NSString *messageBody = #" /*Some HTML format containing HTML5 video player*/";
[controller setMessageBody:messageBody isHTML:YES];
So you need to look for suitable CSS and HTML tags for your video. But don't forget to test it with most e-mail clients as you may see different looks.
Related
Im trying to zip up my sqlite files from my documents directory to send via mail using https://github.com/mattconnolly/ZipArchive.
NSString *filePath = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:#"app.sqlite"];
NSString *filePath2 = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:#"app.sqlite-shm"];
NSString *filePath3 = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:#"app.sqlite-wal"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *archivePath = [documentsDirectory stringByAppendingString:#".zip"];
//Zip up files
ZipArchive *archiver = [[ZipArchive alloc] init];
[archiver CreateZipFile2:archivePath];
[archiver addFileToZip:filePath newname:#"backUp.sqlite"];
[archiver addFileToZip:filePath2 newname:#"backUp.sqlite-shm"];
[archiver addFileToZip:filePath3 newname:#"backUp.sqlite-wal"];
MFMailComposeViewController *mailView = [[MFMailComposeViewController alloc] init];
if (mailView != nil) {
mailView.mailComposeDelegate = self;
[mailView setSubject:#"Database"];
//Attach zip file
[mailView addAttachmentData:[NSData dataWithContentsOfFile:archivePath] mimeType:#"application/zip" fileName:#"test.zip"];
[mailView setMessageBody:#"Database attached" isHTML:NO];
[self presentViewController:mailView animated:YES completion: NULL];
}
The attachment appears in the email preview on the device but when it arrives with the recipient the attachment has vanished?
also tried this:
NSString *filePath = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:#"app.sqlite"];
NSString *filePath2 = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:#"app.sqlite-shm"];
NSString *filePath3 = [[NSHomeDirectory() stringByAppendingPathComponent:#"Documents"] stringByAppendingPathComponent:#"app.sqlite-wal"];
DebugLog(#"DB path is: %#", filePath);
NSError *error = nil;
NSData *fileData = [[NSData alloc] initWithContentsOfFile:filePath options:0UL error:&error];
NSString* fileDataString = [[NSString alloc] initWithData:fileData encoding:NSNonLossyASCIIStringEncoding];
NSData *fileData2 = [[NSData alloc] initWithContentsOfFile:filePath2 options:0UL error:&error];
NSString* fileData2String = [[NSString alloc] initWithData:fileData2 encoding:NSNonLossyASCIIStringEncoding];
NSData *fileData3 = [[NSData alloc] initWithContentsOfFile:filePath3 options:0UL error:&error];
NSString* fileData3String = [[NSString alloc] initWithData:fileData3 encoding:NSNonLossyASCIIStringEncoding];
if (error != nil) {
DebugLog(#"Failed to read the file: %#", [error localizedDescription]);
} else {
if (fileData == nil) {
DebugLog(#"File data is nil");
}
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *archivePath = [documentsDirectory stringByAppendingString:#".zip"];
//Zip up documents directory
ZipArchive *archiver = [[ZipArchive alloc] init];
[archiver CreateZipFile2:archivePath];
[archiver addFileToZip:fileDataString newname:#"backUp.sqlite"];
[archiver addFileToZip:fileData2String newname:#"backUp.sqlite-shm"];
[archiver addFileToZip:fileData3String newname:#"backUp.sqlite-wal"];
MFMailComposeViewController *mailView = [[MFMailComposeViewController alloc] init];
if (mailView != nil) {
mailView.mailComposeDelegate = self;
[mailView setSubject:#"Database"];
//Attach zip file
[mailView addAttachmentData:[NSData dataWithContentsOfFile:archivePath] mimeType:#"application/zip" fileName:#"test.zip"];
[mailView setMessageBody:#"Database attached" isHTML:NO];
[self presentViewController:mailView animated:YES completion: NULL];
}
same behaviour zip file does not arrive with email
Logging the archivePath gives me /var/mobile/Containers/Data/Application/1D32A3AA-A431-46234-AE4B-ED944CA2D883F4/Documents.zip
Typically an email attachment doesn't arrive for one of two reasons:
The path you used to load the NSData resulted in the data being nil.
The file is too large to send via email.
You have several issues leading to problem one.
The path for the zip file is in a read-only folder - the root of your app's resource bundle.
Never use NSHomeDirectory() to create paths to folders in your app's sandbox. Things changed in iOS 8 and such paths won't work at all. Only use NSSearchPathForDirectoriesInDomains with the proper folder reference such as NSDocumentDirectory.
To solve the first issue, change this:
NSString *archivePath = [documentsDirectory stringByAppendingString:#".zip"];
to something like:
NSString *archivePath = [documentsDirectory stringByAppendingPathComponent:#"SomeFiles.zip"];
It would be even better to store this temporary file in the caches folder (use NSCachesDirectory instead of NSDocumentDirectory). Then delete the file after sending the email.
I want to attach a .csv file to an email so the user can send it. At this point, I know the file is actually created when I'm working in the simulator (I can find and open it), and it appears to be attached to the email which is created. However, since I can't send email from the sim, that's as far as I get there.
Deployed on my iPad, the indications are that the file is created and attached to the email (correctly titled file icon included in body of email). I can email it, but no file is attached when the email is received.
Here's the code I'm using to create and write to the file:
-(NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(#"dataFilePath created");
return [documentsDirectory stringByAppendingPathComponent:#"WMDGstats.csv"];
NSLog(#"File path: %#", documentsDirectory);
}
-(void) createCSVFile
{
NSLog(#"Top of createCSVFile");
// [[NSFileManager defaultManager] removeItemAtPath:pngFilePath error:&error];
if (![[NSFileManager defaultManager] fileExistsAtPath:[self dataFilePath]])
{
[[NSFileManager defaultManager] createFileAtPath: [self dataFilePath] contents:nil attributes:nil];
NSLog(#"File created");
}
...yada, yada data creation
NSFileHandle *handle;
handle = [NSFileHandle fileHandleForWritingAtPath: [self dataFilePath] ];
[handle truncateFileAtOffset:0];
[handle writeData:[fullString dataUsingEncoding:NSUTF8StringEncoding]];
[self mailCSV];
}
And here's the way I attach it to the email:
-(void) mailCSV
{
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[mail setSubject:#"Subject"];
[mail setMessageBody:#"message body" isHTML:NO];
[mail setToRecipients:#[#"testingEmail#example.com"]];
NSData *WMDGData = [NSData dataWithContentsOfFile:#"WMDGstats.csv"];
[mail addAttachmentData:WMDGData mimeType:#"text.csv" fileName:#"WMDGstats.csv"];
[self presentViewController:mail animated:YES completion:NULL];
}
else
{
NSLog(#"This device cannot send email");
}
}
Any ideas?
Thanks for looking!
Edit:
Per rmaddy's kind guidance in his comment below, I supplied the full file path for the file:
NSData *WMDGData = [NSData dataWithContentsOfFile:[documentsDirectory stringByAppendingPathComponent:#"WMDGstats.csv"]];
And it works perfectly--file created, attached, mailed and received!
Thanks rmaddy!!!
The following line:
NSData *WMDGData = [NSData dataWithContentsOfFile:#"WMDGstats.csv"];
is probably returning nil because you need to specify the proper path to the file. Since you are saving the file in the Documents folder, you need to specify that full path.
I am generating a pdf from html and attaching to email. The problem I have is the pdf is attaching to the email before it has finished generating.
I have tried using a completion block but without success.
#property (nonatomic, strong) void(^completionHandler)(BOOL);
[self generatePDF:html andCompletionHandler:^(BOOL result) {
// COMPLETED ? - ATTACH the file
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pdfPathFile=[docDir stringByAppendingString:#"/report.pdf"];
NSData *pdfData = [NSData dataWithContentsOfFile:pdfPathFile];
[controller setMessageBody:#"report attached" isHTML:NO];
[controller addAttachmentData:pdfData mimeType:#"application/pdf" fileName:#"report.pdf"];
NSLog(#"attaching pdf with length %d",[pdfData length]);
}];
-(void)generatePDF:(NSMutableString*)HtmlString andCompletionHandler:(void (^)(BOOL result))handler{
_completionHandler = handler;
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pdfPathFile=[docDir stringByAppendingString:#"/report.pdf"];
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error;
if ([fm fileExistsAtPath:pdfPathFile] == YES){
[fm removeItemAtPath:pdfPathFile error:&error];
}
//I am using NDHTMLtoPDF to create the PDF
self.PDFCreator = [NDHTMLtoPDF createPDFWithHTML:HtmlString pathForPDF:pdfPathFile delegate:self pageSize:kPaperSizeA4 margins:UIEdgeInsetsMake(10,5,10,5)];
}
#pragma mark NDHTMLtoPDFDelegate
- (void)HTMLtoPDFDidSucceed:(NDHTMLtoPDF*)htmlToPDF
{
NSString *result = [NSString stringWithFormat:#"HTMLtoPDF did succeed - %#", htmlToPDF.PDFpath];
NSLog(#"%#",result);
_completionHandler(YES);
}
I have implemented the module for sending the email from my iPhone device to server. When it comes to the implementation, there is no email file attach instead. I sweared I have added the attACHMENT . THE below is my working
-(IBAction)sendMail:(id)sender{
NSArray *toRecipents = [NSArray arrayWithObjects:#"birth.lo#sdsdfsfsdf-hk.com",#"jason.li#asdasdad-hk.com",#"lo.sdad#gmail.com",nil];
mailComposer = [[MFMailComposeViewController alloc]init];
if ([MFMailComposeViewController canSendMail]) {
mailComposer.mailComposeDelegate = self;
[mailComposer setSubject:#"NOXAV testing"];
[mailComposer setToRecipients:toRecipents] ;
[mailComposer setMessageBody:#"Testing message for the test mail" isHTML:NO];
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/textfile.txt",
documentsDirectory];
NSData *fileData = [NSData dataWithContentsOfFile:fileName];
NSString *mimeType = #"text/html";
[mailComposer addAttachmentData:fileData mimeType:mimeType fileName:fileName];
[self presentModalViewController:mailComposer animated:YES ];
}
}
-(void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
if (result) {
NSLog(#"Result : %d",result);
}
if (error) {
NSLog(#"Error : %#",error);
}
[self dismissModalViewControllerAnimated:YES];
}
The MIME type for text file should be text/plain,So change
NSString *mimeType = #"text/html";
to
NSString *mimeType = #"text/plain";
Edit
Also change the fileName here
[mailComposer addAttachmentData:fileData mimeType:mimeType fileName:#"textfile.txt"];
Looks like file name problem, change following statement along with above suggested by Yogesh -
//make a file name to write the data to using the documents directory:
NSString * fileName = [documentsDirectory stringByAppendingPathComponent:#"textfile.txt"];
NSData *fileData = [NSData dataWithContentsOfFile:fileName];
NSString *mimeType = #"text/plain";
Your fileData may not be getting the data from file. Check if [filedata length] = some value.
i try to send a audio record by file aac (kAudioFormatMPEG4AAC) format but the file attached it's doesn't send
*myString = file://localhost/private/var/mobile.......
here is my code
MFMailComposeViewController *picker =
[[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"My Audio File"];
NSString *fileName = #"Rec.aac";
NSString *documentsDirectory = myString ;
NSString *path = [documentsDirectory stringByAppendingPathComponent:fileName];
NSData *data = [NSData dataWithContentsOfFile:path];
[picker addAttachmentData:data mimeType:#"audio/aac"
fileName:fileName];
NSString *emailBody = #"AAC format sound file attached.";
[picker setMessageBody:emailBody isHTML:YES];
[self presentModalViewController:picker animated:YES];
[picker release];
NSData *data = [NSData dataWithContentsOfFile:path];
You're passing in a file:// URL, which won't be understood by that method. That method expects just a standard file path, i.e. /private/var/mobile/.
You could simply use the file path, but if you're only provided with a URL form string, you can create a URL object and use that with NSData.
NSURL* fileURL = [NSURL URLwithString:myString];
NSError* error = nil;
NSData* data = [NSData dataWithContentsOfURL:fileURL options:0 error:&error];
if (error) {
NSLog(#"Unable to load file from provided URL %#: %#", myString, error);
}