如何使用POST请求向SendGrid发送iOS中的照片电子邮件附件?

时间:2016-08-11 16:10:28

标签: php ios sendgrid

我正在使用NSMutableURLRequest将POST数据发送到使用SendGrid发送电子邮件的服务器端PHP脚本。这很好用。但是,我不知道如何正确打包UIImagedata作为附件发送。这是我目前的代码:

// 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 = @"blabla@blabla.com";
    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];
}

如果您研究此问题,您可能会发现现有的iOS SendGrid库。不幸的是,这不是答案。由于安全问题,SendGrid的人告诉我不要使用lib。

1 个答案:

答案 0 :(得分:2)

新答案:

要将文件作为电子邮件附件直接上传到SendGrid,您应该使用Web API v3并按docs中所述创建请求。

首先,您需要add authentication header来处理您的请求。 其次,您需要将数据转换为JSON格式。如果我们在讨论文件,您需要使用Base64对文件数据进行编码,如body parameters section中所述:

JSON PARAMETER: attachements/content
TYPE: string
REQUIRED: Yes
The Base64 encoded content of the attachment.

另外,请查看dispositioncontent_id参数:它们将帮助您通过邮件设置文件外观。

旧回答:

上传参数和文件的标准方法是使用multipart messages的POST请求。我已更改您的代码以创建此格式的数据:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
  UIImage* image = info[UIImagePickerControllerEditedImage];
  NSDictionary* params = @{
    @"toEmailAddress" : @"blabla@blabla.com",
    @"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];
}

您可以使用$_POST$_FILES变量来访问PHP脚本中已加载的数据。 如果您想了解有关多部分邮件的详情,请查看文档here