如何使用Gmail OAuth API发送电子邮件(特别是通过SMTP)?

14

我正在开发一个web应用程序,该应用程序将代表已登录用户发送电子邮件。

我尝试使用Google最新发布的Gmail OAuth协议(描述在这里)通过用户的Gmail帐户发送这些邮件(最好使用SMTP而不是IMAP,但我很容易上手)。

  1. 所有示例代码都基于IMAP而不是SMTP。如果你不打算向人们展示如何使用SMTP,为什么要"支持"它?
  2. 示例代码给我的一个致命错误,来自未捕获的Zend异常——它找不到"INBOX"文件夹。

致命错误:未捕获的异常'Zend_Mail_Storage_Exception',信息为'不能更改文件夹,也许它不存在'在路径\to\xoauth-php-samples\Zend\Mail\Storage\Imap.php:467中堆栈跟踪:#0路径\to\xoauth-php-samples\Zend\Mail\Storage\Imap.php(248):Zend_Mail_Storage_Imap->selectFolder('INBOX') #1路径\to\xoauth-php-samples\three-legged.php(184):Zend_Mail_Storage_Imap->__construct(Object(Zend_Mail_Protocol_Imap))#2 {main} 下一个异常 'Zend_Mail_Storage_Exception',信息为'无法选择INBOX,这是有效的传输吗?'在路径\to\xoauth-php-samples\Zend\Mail\Storage\Imap.php:254中堆栈跟踪:#0路径\to\xoauth-php-samples\three-legged.php(184):Zend_Mail_Storage_Imap->__construct(Object(Zend_Mail_Protocol_Imap))#1 {main} 在路径\to\xoauth-php-samples\Zend\Mail\Storage\Imap.php的第254行

我已经确认收到了好的OAuth令牌,但是我不知道如何进行实际的电子邮件发送操作。由于这个协议还比较新,因此没有太多非官方社区文档介绍,而官方文档则只是关于SMTP RFC的干巴巴的内容,没有什么帮助。如果有人能够帮助我启动它,我将非常感激。

注意:我已经成功地通过SSL连接到Gmail的SMTP服务器并发送电子邮件,前提是用户提供我的应用程序他/她的Gmail用户名和密码。我想避免这种方法,因为它会鼓励网络钓鱼,安全意识强的用户也不会接受它。这个问题不涉及这方面。


因为我是新手,Stack Overflow 的垃圾邮件过滤器要求我删除到 Gmail OAuth 公告(http://googlecode.blogspot.com/2010/03/oauth-access-to-imapsmtp-in-gmail.html)和示例代码(http://code.google.com/p/google-mail-xoauth-tools/wiki/PhpSampleCode)的链接。 - Curtis Gibby
你能否仅使用JavaScript创建一个Web应用程序,通过Gmail发送电子邮件,告诉Gmail服务器代表用户发送它? - Muhammad Umer
2个回答

4
我正在使用Google应用账户,并尝试创建一个应用程序,允许我的用户通过新的Oauth授权通过SMTP发送邮件。我能够使用这个讨论中的一些信息使其工作。然而,我认为我应该澄清一些我遇到的问题...
1)SMTP的Zend框架显然会自动查找Zend/Mail/Protocol/Smtp/Auth文件夹中的.php文件,在这种情况下是“Xoauth.php”,但在Zend中通常不存在。我成功地通过将现有的Login.php文件复制到Xoauth.php并根据这个网页上的建议稍微修改它来完成了这个操作。
这非常有帮助,但这只是Xoauth.php文件的一部分(编辑login.php的副本,您将看到一个等效的区域)。
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH XOAUTH ' . $this->_xoauth_request);
$this->_expect(235);
$this->_auth = true;

2) 请注意,即使您在PHP中直接引用Zend,也应该将其放在PHP include_path中,因为它可能会尝试使用其Loader.php文件引用自身而不使用显式路径。

3) 除了删除明显的IMAP函数并将它们替换为等效的SMTP函数外,我没有必要更改Google OAuth PHP示例代码。我确实需要包含Zend/Mail.php文件以发送电子邮件,并添加必要的代码以使测试工作。


太棒了!我遇到了与Curtis相同的错误,按照你在步骤1中提到的方法解决了问题! - Abhinav Manchanda

2

您是否使用 Google Apps 帐户?

在重定向至 OAuthAuthorize 令牌 URL 时,我错误地指定了 hd=default。这告诉 OAuth 端点为标准 Google 帐户授权令牌,它与 Google Apps 不兼容。

因此,在 three-legged.php 中,将以下行替换为:

$consumer->redirect(array('hd' => 'default'));

使用

$consumer->redirect();

一切应该都没问题——如果同时使用个人和Google应用程序账户登录,则应要求您选择其中一个帐户。

希望这可以帮到您——我将修补代码以解决此问题。

祝好, - Ryan

关于使用SMTP——我还没有完全掌握这项技术并且文档化,但以下是基本信息。

1)创建Zend/Mail/Protocol/Smtp/Auth/Xoauth.php,其中auth()方法相当简单:

// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH XOAUTH ' . $this->_xoauth_request);
$this->_expect(235);
$this->_auth = true;

2) 生成$initClientRequest的方式略有不同,因为SMTP和IMAP的URL不同。 3) 发送如下邮件:

  // where getXoauthClientRequest abstracts out line 116-165 in existing three-legged.php
  $smtpInitClientRequestEncoded = getXoauthClientRequest($smtpUrl, $accessToken);

  $config = array('ssl' => 'ssl',
                  'port' => '465',
                  'auth' => 'xoauth',
                  'xoauth_request' => $smtpInitClientRequestEncoded);

  $transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config);
  $mail = new Zend_Mail();
  $mail->setBodyText('This is the text of the mail.');
  $mail->setFrom($email_address, 'Some Sender');
  $mail->addTo($email_address, 'Some Recipient');
  $mail->setSubject('TestSubject');
  $mail->send($transport);

我将尝试创建更好文档化的内容——不需要在Zend“命名空间”中创建类,但可能需要扩展Zend_Mail_Transport_Smtp,因为_sendMail()是在那里编写的,只从Zend_Mail_Protocol_Smtp_Auth_*“包”中加载auth类。


Ryan,谢谢你提供的信息。我会尝试运行这段代码并看看结果如何。感谢你在这方面的努力。我并不是想通过Google Apps账户发送电子邮件,只是使用普通的Gmail。 - Curtis Gibby
我正在尝试自己让它工作。我不理解这一行代码:$smtpInitClientRequestEncoded = getXoauthClientRequest($smtpUrl, $accessToken); 我应该从哪里获取或如何创建getXoauthClientRequest函数? - PaulM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接