通过Gmail API发送电子邮件 - 目标C.

时间:2017-03-14 03:10:05

标签: ios objective-c google-api gmail-api appauth

我们正在开发一个涉及通过Gmail API发送电子邮件的iOS项目,但我们无法找到有关如何实际执行此操作的文档。

首先,我们还没有完全弄清楚身份验证。我们正在使用AppAuth来处理这个问题,到目前为止它运作良好,但我们不太确定如何将其与我们代码中的Gmail API相关联。

其次,我们如何发送消息本身?我们有内容和格式化的所有内容,我们无法弄清楚如何实际发送消息。我们要做的就是从用户自己的电子邮件帐户向指定的电子邮件地址发送简单的邮件;没有附件或类似的东西。我们已经看到了几个快速的例子,但是我们更愿意使用Objective C.关于我们如何做到这一点的任何想法?

更新

在玩完一些东西之后,我们找到了另一种连接Gmail的方法。我们只是尝试使用HTTP POST方法发送电子邮件,而不是使用Google API Objective C Client for REST中的类。这似乎比处理我们之前遇到的所有错误更容易。我们现在唯一的问题是我们仍然无法发送消息。几乎我们尝试过的所有内容,API只会创建一个空消息并将其放入我们的已发送邮箱中;那就是它。这就是我们现在所拥有的:

- (void)sendEmail{
    NSURL *userinfoEndpoint = [NSURL URLWithString:@"https://www.googleapis.com/upload/gmail/v1/users/TEST_USERNAME/messages/send?uploadType=media"];
    NSString *currentAccessToken = _authState.lastTokenResponse.accessToken;

    [self logMessage:@"Trying to authenticate...."];

    // Handle refreshing tokens

    NSString *message = [NSString stringWithFormat:@"{\"raw\": \"%@\"}",[self generateMessage]];
    NSLog(@"%@", message);

    // creates request to the userinfo endpoint, with access token in the Authorization header
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:userinfoEndpoint];
    NSString *authorizationHeaderValue = [NSString stringWithFormat:@"Bearer %@", accessToken];
    [request addValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"message/rfc822" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[message length]] forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:[message dataUsingEncoding:NSUTF8StringEncoding];

    NSURLSessionConfiguration *configuration =
    [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
                                                          delegate:nil
                                                     delegateQueue:nil];
    // performs HTTP request
    NSURLSessionDataTask *postDataTask =
    [session dataTaskWithRequest:request
               completionHandler:^(NSData *_Nullable data,
                                   NSURLResponse *_Nullable response,
                                   NSError *_Nullable error) {
                  // Handle response
               }];

    [postDataTask resume];
}];

}
- (NSString *)generateMessage{
    NSString *message = [NSString stringWithFormat:@"From: <TEST_USER@domain.com>\nTo: <TEST_USER@domain.com>\nSubject: Test\n\nThis is a test"];
    NSString *rawMessage = [message stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"];

    NSData *encodedMessage = [rawMessage dataUsingEncoding:NSUTF8StringEncoding];
    NSString *encoded = [encodedMessage base64EncodedStringWithOptions:0];
    NSLog(@"%@", encoded);

    return encoded;
}

我们已经测试了编码部分,它正在制作一个合适的base64字符串,但是在那之后,某些内容显然没有正确格式化。我们得到消息已成功创建的确认,但所有API都会创建一个没有收件人,主题或正文的空电子邮件。关于如何使其发挥作用的任何想法?

2 个答案:

答案 0 :(得分:0)

我不是这方面的专家,但我记得我们过去做过类似的事情。按照以下链接中的说明操作,确保在Gmail API向导中选择正确的选项

https://developers.google.com/gmail/api/quickstart/ios?ver=objc

enter image description here

enter image description here

我希望你能找到这个有用的

答案 1 :(得分:0)

经过无数次试验,以下代码似乎终于对我有用,我在上面的示例中完成了该工作。

首先,您需要在开发人员控制台中创建Google项目,获取其客户端ID和Api-Key(这可能不是必需的),并在-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions :( NSDictionary *)launchOptions方法:

[GIDSignIn sharedInstance].clientID = @"your proj client id here";
[GIDSignIn sharedInstance].delegate = self;
[GIDSignIn sharedInstance].scopes=[NSArray arrayWithObjects:@"https://www.googleapis.com/auth/gmail.send",@"https://www.googleapis.com/auth/gmail.readonly",@"https://www.googleapis.com/auth/gmail.modify", nil];

现在发送电子邮件:

// refresh token
appDelegate.delAuthAccessToken=@"";
[[GIDSignIn sharedInstance] signInSilently];
NSDate *timeStart = [NSDate date];
NSTimeInterval timeSinceStart=0;
while([appDelegate.delAuthAccessToken isEqualToString:@""] && timeSinceStart<10){//wait for new token but no longer than 10s should be enough
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                             beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0f]];//1sec increment actually ~0.02s
    timeSinceStart = [[NSDate date] timeIntervalSinceDate:timeStart];
}
if (timeSinceStart>=10) {//timed out
    return;
}

//compose rfc2822 message AND DO NOT base64 ENCODE IT and DO NOT ADD {raw etc} TOO, put 'To:' 1st, add \r\n between the lines and double that before the actual text message
NSString *message = [NSString stringWithFormat:@"To: %@\r\nFrom: %@\r\nSubject: EzPic2Txt\r\n\r\n%@", appDelegate.delToEmails, appDelegate.delAuthUserEmail, appDelegate.delMessage];

NSURL *userinfoEndpoint = [NSURL URLWithString:@"https://www.googleapis.com/upload/gmail/v1/users/me/messages/send?uploadType=media"];

NSLog(@"%@", message);

//create request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:userinfoEndpoint];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[message dataUsingEncoding:NSUTF8StringEncoding]];//message is plain UTF8 string

//add all headers into session config, maybe ok adding to request too
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
configuration.HTTPAdditionalHeaders = @{
 @"api-key"       : @"api-key here, may not need it though",
 @"Authorization" : [NSString stringWithFormat:@"Bearer %@", appDelegate.delAuthAccessToken],
 @"Content-type"  : @"message/rfc822",
 @"Accept"        : @"application/json",
 @"Content-Length": [NSString stringWithFormat:@"%lu", (unsigned long)[message length]]
 };
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

 // performs HTTP request
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
                                                    // Handle response
                                                }];
 [postDataTask resume];

希望对别人有帮助

在我的应用中,我曾经能够使用MailCore2,但由于它仅在具有完全权限的情况下才能被Google封锁。 Google允许我仅使用发送,只读和修改范围。尽管没有指导方针,如何在iOS的Gmail中使用其“伟大的Restful api”,所以似乎HTTP POST是最后的手段,直到他们也将其关闭。