I am using NSMutableURLRequest to send POST data to a server-side PHP script that sends emails using SendGrid. This works just fine. However, I have no idea how to package UIImagedata properly to send as an attachment. Here is my current code:
// Choose an image from your photo library
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
chosenImage = info[UIImagePickerControllerEditedImage]; // chosenImage = UIImage
pickedData = UIImagePNGRepresentation(chosenImage); // pickedData = NSData
attachment = TRUE;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
-(void)sendMail {
toEmailAddress = @"[email protected]";
subject = @"Some Subject";
message = @"Some message...";
fullName = @"Mister Bla Bla";
if (attachment == TRUE) {
// Create NSData object as PNG image data from camera image
NSString *picAttachment = [NSString stringWithFormat:@"%lu",(unsigned long)[pickedData length]];
NSString *picName = @"Photo";
post = [NSString stringWithFormat:@"&toEmailAddress=%@&subject=%@&message=%@&fullName=%@&picAttachment=%@&picName=%@", toEmailAddress, subject, message, fullName, picAttachment, picName];
} else {
post = [NSString stringWithFormat:@"&toEmailAddress=%@&subject=%@&message=%@&fullName=%@", toEmailAddress, subject, message, fullName];
}
NSData * postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSString * postLength = [NSString stringWithFormat:@"%lu",(unsigned long)[postData length]];
NSMutableURLRequest * request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.someURL.com/sendgrid.php"]]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
// send the POST request, and read the reply by creating a new NSURLSession:
NSURLSession *conn = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[conn dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"requestReply: %@", requestReply); // Return response from PHP script on server.
}] resume];
}
If you research this question, you may find that there is an existing iOS SendGrid lib. Unfortunately, this is not the answer. The folks at SendGrid tell me not to use the lib because of a security concern.
New answer:
To upload file as email attachement directly to SendGrid you should use Web API v3 and create request as described in docs.
First of all, you need to add authentication header to your request. Secondly, you need to convert your data to JSON format. If we are talking about files, you need to encode you file data with Base64, as described in body parameters section:
JSON PARAMETER: attachements/content
TYPE: string
REQUIRED: Yes
The Base64 encoded content of the attachment.
Also, take a look to disposition
and content_id
params: they will help you to setup your file appearance in mail.
Old answer:
The standard way of uploading both parameters and files is using POST request with multipart messages. I have change your code to create data of this format:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage* image = info[UIImagePickerControllerEditedImage];
NSDictionary* params = @{
@"toEmailAddress" : @"[email protected]",
@"subject" : @"Some Subject",
@"message" : @"Some message...",
@"fullName" : @"Mister Bla Bla",
};
[picker dismissViewControllerAnimated:YES completion:^{
[self sendMailWithParams:params image:image];
}];
}
static NSStringEncoding const kEncoding = NSUTF8StringEncoding;
- (void)sendMailWithParams:(NSDictionary*)params image:(UIImage*)image {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
request.URL = [NSURL URLWithString:@"http://www.someURL.com/sendgrid.php"];
request.HTTPMethod = @"POST";
NSString *boundary = [NSUUID UUID].UUIDString;
// define POST request as multipart
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
// prepare boundary
NSString *middleBoundary = [NSString stringWithFormat:@"--%@\r\n", boundary];
NSData *middleBoundaryData = [middleBoundary dataUsingEncoding:kEncoding];
NSMutableData* body = [NSMutableData data];
// append params
[params enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) {
[body appendData:middleBoundaryData];
NSData* fieldData = [self dataForKey:key value:value];
[body appendData:fieldData];
}];
// append image
if (image) {
[body appendData:middleBoundaryData];
NSData* imageData = [self dataForImage:image imageName:@"photo.png"];
[body appendData:imageData];
}
// add last boundary
NSString* lastBoundary = [NSString stringWithFormat:@"--%@--\r\n", boundary];
NSData* lastBoundaryData = [lastBoundary dataUsingEncoding:kEncoding];
[body appendData:lastBoundaryData];
// set body to request
request.HTTPBody = body;
// add length of body
NSString *length = [NSString stringWithFormat:@"%llu", (uint64_t)body.length];
[request setValue:length forHTTPHeaderField:@"Content-Length"];
// send request
NSURLSession* session = [NSURLSession sharedSession];
NSURLSessionDataTask* task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
// handle as you want
}];
[task resume];
}
- (NSData*)dataForImage:(UIImage*)image imageName:(NSString*)imageName {
NSString* fieldDescription = [NSString stringWithFormat:
@"Content-Disposition: form-data; name=\"image\"; filename=\"%@\"\r\n"
@"Content-Type: image/png\r\n\r\n", imageName];
NSMutableData *data = [NSMutableData data];
[data appendData:[fieldDescription dataUsingEncoding:kEncoding]];
NSData* imageData = UIImagePNGRepresentation(image);
[data appendData:imageData];
NSString* newLine = @"\r\n";
NSData* newLineData = [newLine dataUsingEncoding:kEncoding];
[data appendData:newLineData];
return data;
}
- (NSData*)dataForKey:(NSString*)key value:(NSString*)value {
NSString* fieldDescription = [NSString stringWithFormat:
@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n"
@"%@\r\n", key, value];
return [fieldDescription dataUsingEncoding:kEncoding];
}
You can use $_POST and $_FILES variables to get access to loaded data in your PHP script. If you want to learn more about multipart messages, check docs here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With