urllib2 HTTPPasswordMgrWithDefaultRealm'失败' 5个请求后的密码

时间:2014-07-10 00:00:35

标签: python urllib2 basic-authentication

mailgun API发送电子邮件时,我遇到了一个我无法解决的奇怪的Python问题:urllib2.HTTPPasswordMgrWithDefaultRealm()创建的PasswordMgr似乎在4-5次尝试后丢失了密码,然后我得到401身份验证错误。

相同的API密钥稍后用于以后运行相同的代码,因此我100%确定它是有效的,如果我重构代码以构建新的HTTPPasswordMgrWithDefaultRealm和{ {1}} opener内的{1}}(见下文)每次提交给API,但这并不是一个好方法。

我在这里创建Email.send_email()并且opener

HTTPPasswordMgrWithDefaultRealm

一旦通过以下调用创建了开启者,它就不会再次创建或由代码修改:

class MailgunConnection(object):

    def __init__(self, domain, api_key):
        self.api_key = api_key 
        self.domain  = domain  ## https://api.mailgun.net
        self.opener  = self.mg_opener()

    def mg_opener(self):            
        passman = urllib2.HTTPPasswordMgrWithDefaultRealm()        
        passman.add_password(None, self.domain, 'api', self.api_key)
        auth_handler = urllib2.HTTPBasicAuthHandler(passman)

        return urllib2.build_opener(auth_handler)

然后将此opener = MailgunConnection(domain, api_key).opener 传递给为每封电子邮件创建的opener

Email

...然后在同一个类的send方法中使用,将电子邮件发送到MailGun的API:

class Email(object):
    def __init__(self, details, opener):
        self.details = details
        self.opener  = opener

它有效......对于4或5个提交...然后我开始从MailGun收到401错误。我确信它不会受到MailGun的限制,也不会影响我传递的参数,首先是相同的代码,然后是重新运行的脚本。

是否还会发生其他可能影响def send_email(self): data = urllib.urlencode(self.details) ## ... snips for brevity ... try: response = self.opener.open('https://api.mailgun.net/v2/my.example.com/messages', data) 创建的揭幕战的事情?

这是在CentOS 5盒子上的Python 2.6.8上。

其他信息: 通过更多的调试和15封电子邮件的测试,我可以看到服务器以相同的方式响应每个请求:urllib2.build_opener请求身份验证。对于发送到API的前6封电子邮件,随后会重新提交调用401的第一个请求,该请求会被401接受并收到电子邮件。

然而,在这6个请求之后,200在请求时停止向服务器发送auth详细信息 - 它只是注册urllib2并且不会将POST数据重新提交给API。

1 个答案:

答案 0 :(得分:1)

好吧,使用requests'解决':

r = requests.post(conf.email_api_gateway,
                auth=('api',     conf.email_api_key),
                data={'to':      self.email_add,
                      'from':    self.get_email_from(),
                      'subject': self.get_email_subject(),
                      'html':    self.get_email_html(),
                      'text':    self.get_email_text() })

## manually set UTF-8 so we can json the response
r.encoding = 'UTF-8'

if r.status_code == 200:
    mail_id = r.json[u"id"]