Email does not attach file - objective-c

I'm using the below code to send a csv via email. The email is send and I received in my Inbox, but I'm not receiving the csv file attached, any idea about what is wrong?
-(void)generateCSV
{
NSFileManager *filemgr = [NSFileManager defaultManager];
NSArray *dirPaths;
NSString *docsDir;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
if ([filemgr fileExistsAtPath:[NSString stringWithFormat:#"%#/test.csv", docsDir] ] == NO)
{
[filemgr createFileAtPath:[NSString stringWithFormat:#"%#/test.csv", docsDir] contents:[#"" dataUsingEncoding: NSUnicodeStringEncoding] attributes: nil];
}
surveyarray = [db retrieveSurvey];
CHCSVWriter * csvWriter = [[CHCSVWriter alloc] initWithCSVFile:[NSString stringWithFormat:#"%#/test.csv", docsDir] atomic:NO];
NSString *str = [NSString stringWithFormat: #"No, CreatedDate, Question1, Question2, Question3, Comment\n"];
[csvWriter writeField:str];
for(int i = 0; i < surveyarray.count; i++)
{
survey = [surveyarray objectAtIndex:i];
NSString *str = [NSString stringWithFormat: #"%d, %#, %#, %#, %#, %#\n", i, survey.createddate, survey.question1, survey.question2, survey.question3, survey.comment];
[csvWriter writeField:str];
}
NSMutableString *subject = [[NSMutableString alloc] init];
NSMutableString *emailBody = [[NSMutableString alloc] init];
[subject appendString:#""];
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:subject];
NSArray *toRecipients = [NSArray arrayWithObjects:#"", nil];
[mailer setToRecipients:toRecipients];
NSData *myData = [NSData dataWithContentsOfFile:[NSString stringWithFormat:#"%#/test.csv", docsDir]];
NSLog(#"%#", myData);
[mailer addAttachmentData:myData mimeType:#"text/csv" fileName:#"test.csv"];
[mailer setMessageBody:emailBody isHTML:NO];
mailer.modalPresentationStyle = UIModalPresentationPageSheet;
[self presentModalViewController:mailer animated:YES];
[mailer release];
[subject release];
[emailBody release];
[csvWriter release];
}
I am generating csv file then send email as attachment.
I open the email in my mailbox, it does not content any attachment.

According to what I see there, I'd say that you forgot to add .csv at the end of your filename :)

According to the NSData class reference, the path given with dataWithContentsOfFile: should be the absolute path. So you should use
[NSString stringWithFormat:#"%#/test.csv", docsDir]
instead of just #"test.csv"
I bet currently your myData is nil or empty.
By the way, I would create an NSString object with the fully qualified path/filename only once and re-use that rather than creating it 3 or 4 times.

This code works for me every time!
http://developer.apple.com/library/ios/#samplecode/MailComposer/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008865

try replacing above line this
[mailer addAttachmentData:myData mimeType:#"text/csv" fileName:#"test.csv"];

finally I solved the problem. The email did attached attachment just the file is empty. This is because the for loop initial with -1 and i change to int i = 0, it works fine now

Related

how to zip and email a file using objective c?

I need to zip my log file and email it. I'm using Objective-zip for zipping my file. And this is my code
-(void)mailLogFile {
if ([MFMailComposeViewController canSendMail]) {
NSDictionary *user = [[DBHelper getSharedInstance] getCurrentUser];
NSString *propertyQuery = [NSString stringWithFormat:#"SELECT RecentActivityId,PropertyPIC,PropertyId,Message,IsSynced,ActivityTime,ErrorCode,ErrorMessage,ErrorData,EntityId,TableNames From RecentActivity ORDER BY ActivityTime desc"];
NSArray *resultArry = [[DBHelper getSharedInstance] getRecordsBySQL:propertyQuery];
NSLog(#"This is the eNVDS in Recent Activity:%#" ,resultArry);
[[DBHelper getSharedInstance] AddLogFile:[NSString stringWithFormat:#"This is the eNVDS in Recent Activity:%#" ,resultArry]];
NSPredicate *notsynced = [NSPredicate predicateWithFormat:#"IsSynced == 0 || IsSynced == %#",#"0"];
NSArray *notsyncedenvds = [resultArry filteredArrayUsingPredicate:notsynced];
NSLog(#"This is the eNVDS in Recent Activity which is not synced:%#" ,notsyncedenvds);
[[DBHelper getSharedInstance] AddLogFile:[NSString stringWithFormat:#"This is the eNVDS in Recent Activity which is not synced:%#" ,notsyncedenvds]];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *WritableDBPath= [documentsDirectory stringByAppendingPathComponent:#"Logfile.txt"];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"test.zip"];
NSData *zipdata = [NSData dataWithContentsOfFile:path];
NSData *data = [NSData dataWithContentsOfFile:WritableDBPath];
//OZZipFile *readFile = [[OZZipFile alloc] initWithFileName:path mode:OZZipFileModeCreate];
OZZipFile *zipFile32= [[OZZipFile alloc] initWithFileName:path mode:OZZipFileModeCreate];
OZZipWriteStream *stream= [zipFile32 writeFileInZipWithName:#"Logfile.txt" compressionLevel:OZZipCompressionLevelBest];
[stream writeData:data];
[stream finishedWriting];
NSString *emailTitle = [NSString stringWithFormat:#"Log file of %#",[NSDate date]];
NSMutableString *messageBody = [NSMutableString stringWithFormat:#"Login with %#",user[#"Username"]];
if(![user[#"PropertyName"] isKindOfClass:[NSNull class]])[messageBody appendFormat:#"\n%#",user[#"PropertyName"]];
[messageBody appendFormat:#"\nApp version : %#",APP_VERSION];
[messageBody appendFormat:#"\nPlease describe your problem scenario here."];
[messageBody appendFormat:#"\n\n\nThanks"];
NSArray *toRecipents = [NSArray arrayWithObject:#"support#aglive.com"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:NO];
[mc setToRecipients:toRecipents];
[mc addAttachmentData:zipdata mimeType:#"application/zip" fileName:#"test.zip"];
[self presentViewController:mc animated:YES completion:nil];
[zipFile32 close];
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Aglive Pro" message:#"You have not configured your mail account. Please configure your mail account from the device settings." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}
}
right now I'm able to send a zip file in email but when I do unzip and open the file in my mobile or mac I get alert saying that The document “Logfile 4.txt” could not be opened. The file isn’t in the correct format. I don't know where I'm going wrong.
This code worked for me
-(void)mailLogFile {
if ([MFMailComposeViewController canSendMail]) {
NSDictionary *user = [[DBHelper getSharedInstance] getCurrentUser];
NSString *propertyQuery = [NSString stringWithFormat:#"SELECT RecentActivityId,PropertyPIC,PropertyId,Message,IsSynced,ActivityTime,ErrorCode,ErrorMessage,ErrorData,EntityId,TableNames From RecentActivity ORDER BY ActivityTime desc"];
NSArray *resultArry = [[DBHelper getSharedInstance] getRecordsBySQL:propertyQuery];
NSLog(#"This is the eNVDS in Recent Activity:%#" ,resultArry);
[[DBHelper getSharedInstance] AddLogFile:[NSString stringWithFormat:#"This is the eNVDS in Recent Activity:%#" ,resultArry]];
NSPredicate *notsynced = [NSPredicate predicateWithFormat:#"IsSynced == 0 || IsSynced == %#",#"0"];
NSArray *notsyncedenvds = [resultArry filteredArrayUsingPredicate:notsynced];
NSLog(#"This is the eNVDS in Recent Activity which is not synced:%#" ,notsyncedenvds);
[[DBHelper getSharedInstance] AddLogFile:[NSString stringWithFormat:#"This is the eNVDS in Recent Activity which is not synced:%#" ,notsyncedenvds]];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *WritableDBPath= [documentsDirectory stringByAppendingPathComponent:#"Logfile.txt"];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Logfile.zip"];
NSData *zipdata = [NSData dataWithContentsOfFile:path];
NSData *data = [NSData dataWithContentsOfFile:WritableDBPath];
OZZipFile *zipFile32= [[OZZipFile alloc] initWithFileName:path mode:OZZipFileModeCreate];
//NSData *zipdata2 = [NSData dataWithContentsOfFile:zipFile32];
OZZipWriteStream *stream= [zipFile32 writeFileInZipWithName:#"LogFile.txt" compressionLevel:OZZipCompressionLevelBest];
[stream writeData:data];
[stream finishedWriting];
[zipFile32 close];
NSString *emailTitle = [NSString stringWithFormat:#"Log file of %#",[NSDate date]];
NSMutableString *messageBody = [NSMutableString stringWithFormat:#"Login with %#",user[#"Username"]];
if(![user[#"PropertyName"] isKindOfClass:[NSNull class]])[messageBody appendFormat:#"\n%#",user[#"PropertyName"]];
[messageBody appendFormat:#"\nApp version : %#",APP_VERSION];
[messageBody appendFormat:#"\nPlease describe your problem scenario here."];
[messageBody appendFormat:#"\n\n\nThanks"];
NSArray *toRecipents = [NSArray arrayWithObject:#"support#aglive.com"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:NO];
[mc setToRecipients:toRecipents];
//
if(zipdata== 0 && zipdata==nil)
{
[self mailLogFile];
}
else
{
[mc addAttachmentData:zipdata mimeType:#"application/zip" fileName:#"Logfile.zip"];
[self presentViewController:mc animated:YES completion:nil];
}

How to attach image in vCard (vcf file) using Objective C?

In my project I need to create and send a vCard (vcf file) that must include an image too. I did everything right except I can not add image to the vCard. I have shared my code below.
- (IBAction)shareButtonPressed:(UIButton *)sender {
NSError *error;
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:#"vCard.vcf"];
[[self vCardRepresentation] writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:#[#"Test", [NSURL fileURLWithPath:filePath]] applicationActivities:nil];
activityVC.excludedActivityTypes = #[UIActivityTypePostToWeibo, UIActivityTypeAssignToContact, UIActivityTypeMessage, UIActivityTypeCopyToPasteboard];
[self presentViewController:activityVC animated:YES completion:^{
}];
}
- (NSString *)vCardRepresentation
{
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:#"Rokon"], 1.0);
[mutableArray addObject:#"BEGIN:VCARD"];
[mutableArray addObject:#"VERSION:3.0"];
[mutableArray addObject:[NSString stringWithFormat:#"FN:%#", #"Rokon"]];
[mutableArray addObject:[NSString stringWithFormat:#"TEL:%#",#"+8801811536248"]];
[mutableArray addObject:[NSString stringWithFormat:#"PHOTO;BASE64:%#",[imageData base64EncodedDataWithOptions:0]]];
[mutableArray addObject:#"END:VCARD"];
return [mutableArray componentsJoinedByString:#"\n"];
}
- (void)shareContact{
[self emptySandbox];
NSString *contactName = [NSString stringWithFormat:#"%# %#",[Person sharedInstance].firstName, [Person sharedInstance].lastName];
NSError *error;
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.vcf", contactName]];
[[self vCardRepresentation] writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:#[contactName, [NSURL fileURLWithPath:filePath]] applicationActivities:nil];
activityVC.excludedActivityTypes = #[UIActivityTypePostToWeibo, UIActivityTypeAssignToContact, UIActivityTypeCopyToPasteboard];
[activityVC setValue:contactName forKey:#"subject"];
[self presentViewController:activityVC animated:YES completion:^{
}];
}
- (NSString *)vCardRepresentation
{
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
NSData *imageData = UIImageJPEGRepresentation([Person sharedInstance].profileImage, 1.0);
[mutableArray addObject:#"BEGIN:VCARD"];
[mutableArray addObject:#"VERSION:3.0"];
[mutableArray addObject:[NSString stringWithFormat:#"FN:%#", [NSString stringWithFormat:#"%#%#", [Person sharedInstance].firstName, [Person sharedInstance].lastName]]];
[mutableArray addObject:[NSString stringWithFormat:#"TEL:%#",[Person sharedInstance].phone]];
[mutableArray addObject:[NSString stringWithFormat:#"email:%#", [Person sharedInstance].email]];
[mutableArray addObject:[NSString stringWithFormat:#"PHOTO;BASE64;ENCODING=b;TYPE=JPEG:%#",[imageData base64EncodedStringWithOptions:0]]];
[mutableArray addObject:#"END:VCARD"];
return [mutableArray componentsJoinedByString:#"\n"];
}
-(void)emptySandbox
{
NSFileManager *fileMgr = [[NSFileManager alloc] init];
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *files = [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:nil];
while (files.count > 0) {
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *directoryContents = [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error];
if (error == nil) {
for (NSString *path in directoryContents) {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:path];
BOOL removeSuccess = [fileMgr removeItemAtPath:fullPath error:&error];
files = [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:nil];
if (!removeSuccess) {
// Error
}
}
} else {
// Error
}
}
}

CSV not attaching to in app email?

So I have had this problem for sometime and just cant get it working! I have been building a survey app that users simply enter information in and its saved to a csv file. Im now at the stage where I need to attached the csv file within the app to an email address...
I just tested this on my new i-phone and there is no attachment when the email is received? Its there in the mail app and in the simulator, however when the message is received on the email account the attachment has gone? Can anyone help?? My code is below:
- (IBAction)send:(id)sender {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedFilePath = [documentsDirectory stringByAppendingPathComponent:#"result‌s.csv"];
NSData *csvData = [NSData dataWithContentsOfFile:savedFilePath];
MFMailComposeViewController *mailcomposer = [[MFMailComposeViewController alloc] init];
[mailcomposer addAttachmentData:csvData mimeType:#"text/csv" fileName:#"results.csv"];
[mailcomposer setToRecipients:#[#"gpsflighttrial#gcap.eu"]];
[mailcomposer setSubject:self.subject.text];
[mailcomposer setMessageBody:self.message.text isHTML:NO];
}
Change your mimeType to #"application/csv" and it will work.
Reason for csv not being attached can be ether of below :
1) filename or filepath is wrong as result nsdata of csv will be nil.
2) filename in addAttachmentData mimeType: fileName: method should cantain only name not type of file format.
Changes in your method is given below :
-(IBAction)send:(id)sender {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// Determine the file name and extension
NSString *strFileName = #"results.csv";
NSArray *filepart = [strFileName componentsSeparatedByString:#"."];
NSString *filename = [filepart objectAtIndex:0];
//get file path
NSString *savedFilePath = [documentsDirectory stringByAppendingPathComponent:strFileName];
//Now check if file exits
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:savedFilePath]){
NSData *csvData = [NSData dataWithContentsOfFile:savedFilePath];
if(csvData)
{
MFMailComposeViewController *mailcomposer = [[MFMailComposeViewController alloc] init];
[mailcomposer addAttachmentData:csvData mimeType:#"text/csv" fileName:filename];
[mailcomposer setToRecipients:#[#"gpsflighttrial#gcap.eu"]];
[mailcomposer setSubject:self.subject.text];
[mailcomposer setMessageBody:self.message.text isHTML:NO];
}
else
NSLog(#"error csv data not created");
}
else
NSLog(#"error file doesnot exists");
}
So after many sleepless nights and a lot of trying different ways I finally found the way that works with a friend (see code below)
NSString *docsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSData *attachment = [NSData dataWithContentsOfFile:[docsDirectory stringByAppendingPathComponent:#"results.csv"]];
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setToRecipients:#[#"gpsflighttrial#gcap.eu"]];
[mailer setSubject:self.subject.text];
[mailer setMessageBody:self.message.text isHTML:NO];
[mailer addAttachmentData:attachment mimeType:#"application/csv" fileName:#"results.csv"];
[self presentModalViewController:mailer animated:YES];
Just in case anyone has this problem in the future.

Can't record or play with a simple recorder?

I have 2 classes, a record and a player. In my main scene, I create an instance of them and play and record. But, as I see, it only records and somehow does not play (the file is not there!)
Here is the code for both :
-(void)record {
NSArray *dirPaths;
NSString *docsDir;
NSString *sound= #"sound0.caf" ;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ;
docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath = [docsDir stringByAppendingPathComponent:sound];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax],
AVEncoderAudioQualityKey, nil];
NSError *error;
myRecorder = [[AVAudioRecorder alloc] initWithURL:soundFileURL settings:settings error:&error];
if (myRecorder) {
NSLog(#"rec");
[myRecorder prepareToRecord];
myRecorder.meteringEnabled = YES;
[myRecorder record];
} else
NSLog( #"error" );
}
I can see the log of rec.
-(void)play {
NSArray *dirPaths;
NSString *docsDir;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *soundFilePath1 = #"sound0.caf" ;
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath1];
BOOL isMyFileThere = [[NSFileManager defaultManager] fileExistsAtPath:soundFilePath1];
if(isMyFileThere) {
NSLog(#"PLAY");
avPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:NULL];
avPlayer1.volume = 8.0;
avPlayer1.delegate = self;
[avPlayer1 play];
}
}
I DONT SEE THE LOG OF PLAY !
I call them both with:
recInst=[recorder alloc]; //to rec
[recInst record];
plyInst=[player alloc]; //play
[plyInst play];
and to stop the recorder:
- (void)stopRecorder {
NSLog(#"stopRecordings");
[myRecorder stop];
//[myRecorder release];
}
What's wrong here? Thanks.
In your record method, you're appending the file name to the path with:
NSString *soundFilePath = [docsDir stringByAppendingPathComponent:#"sound0.caf"];
You do not do that in your play method, so it's looking for the file in whatever the current working directory is, rather than the Documents directory.
You need to do:
NSString *soundFilePath1 = [docsDir stringByAppendingPathComponent:#"sound0.caf"];
instead of:
NSString *soundFilePath1 = #"sound0.caf" ;
And just another note: soundFilePath and soundFilePath1 are both local variables. Therefore, they are not visible outside their respective methods. Thus, it's not necessary to give them different names. You can call them both soundFilePath and there will not be a conflict.

Repeating UIAlert code over and over

I have this code:
-(IBAction)action2:(id)sender{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Confirm" message:#"If you press of a new group with the name you have set will be created" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles: #"Ok", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Ok"])
{
NSString *destDir = [NSString stringWithFormat:#"/sandbox/%#/", namegroup.text];
NSString *filename5 = namegroup.text;
NSString *filename6 = #"group";
NSString *filename7 = #"groupdata";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *getImagePath5 = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:#"%#", filename7]];
NSMutableArray *titles = [NSMutableArray array];
[titles addObject:filename5];
NSMutableArray *keys = [NSMutableArray array];
[keys addObject:filename6];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:titles forKeys:keys];
NSString *jsonString = [dict JSONRepresentation];
NSData *jsonData = [jsonString dataUsingEncoding: NSUTF8StringEncoding];
[jsonData writeToFile: getImagePath5 atomically: YES];
[[self restClient] uploadFile:filename7 toPath:destDir
withParentRev:nil fromPath:getImagePath5];
}
}
If I press Ok button, the code is repeated over and over. how can I repeat it only 1 time??
I found out that there was another alert with the same cancel title, and when this was pressed it re-launched the same code. Thanks however for the help.