Hi Jan,
Attached are the MailAutoConfigure class and header files. I will upload
to github later.
I wasn't aware of either the work that Boren is doing or RFC 6186.
I will contact Boren regarding his work.
Having just given RFC 6186 a cursory read it doesn't look too difficult
to add in to the existing DNS record checks.
I am wondering, though, whether it might be best to separate each
individual method of auto-configuration into classes, with a control
class running through each method (either simultaneously or
sequentially) to return the configuration in the shortest possible time.
Thanks
Matt
On 20/07/14 21:20, Jan Kundrát wrote:
> On Sunday, 20 July 2014 13:18:34 CEST, Matt Richardson wrote:
>> I have written a class which takes a users email address and uses the
>> domain or the DNS MX records for that domain to lookup the email server
>> settings from the Mozilla ISP Database.
>
> Sounds cool, looking forward for reviewing this. Quick question,
> because the referred Mozilla wiki page conspicuously misses RFC 6186
> [1] -- are you aware of that? Are you in touch with some of the work
> that Boren (IIRC) is doing in this area? Or am I mistaken and it's
> actually you?
>
>> I was wondering whereabouts in the Trojita source tree to put this
>> class?
>
> Sounds like a material for a standalone top-level directory.
>
>> I was also wondering about naming convention within Trojita. At the
>> moment the class is called MailAutoConfigure but I don't know if people
>> would prefer a different name.
>
> Depends on how the entire API looks like. Please show us the code and
> how the functionality is split into different classes, and then we can
> talk about proper naming conventions.
>
> With kind regards,
> Jan
>
> [1] http://tools.ietf.org/html/rfc6186
>
#include "mailautoconfigure.h"
MailAutoConfigure::MailAutoConfigure(QObject *parent, QString emailAddress) :
QObject(parent)
{
m_confInfo = new SettingsObject();
m_isEmailDomain = true;
m_emailDomain = emailAddress.remove(0,emailAddress.indexOf("@")+1);
m_testDomain = m_emailDomain;
qDebug() << "Domain:" << m_testDomain;
}
void MailAutoConfigure::getConf() {
getServerName();
}
void MailAutoConfigure::getServerName()
{
networkFileExists(QUrl(tr("https://autoconfig.thunderbird.net/v1.1/%1").arg(m_testDomain)));
}
void MailAutoConfigure::networkFileExists(QUrl u)
{
QNetworkAccessManager *nam = new QNetworkAccessManager();
QNetworkRequest netRequest;
netRequest.setUrl(u);
m_netReply = nam->get(netRequest);
connect(m_netReply,SIGNAL(metaDataChanged()),this,SLOT(fileExistsReply()));
}
void MailAutoConfigure::fileExistsReply()
{
if(m_netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) {
connect(m_netReply,SIGNAL(finished()),this,SLOT(getServerInfo()));
}
else {
if(m_testDomain.contains(".")) {
m_testDomain = stripSubdomain(m_testDomain);
getServerName();
}
else {
if(m_isEmailDomain) {
m_isEmailDomain = false;
m_testDomain = m_emailDomain;
lookupServer();
}
else
emit finished(m_confInfo);
}
}
}
QString MailAutoConfigure::stripSubdomain(QString dmn)
{
return dmn.remove(0,dmn.indexOf(".")+1);
}
void MailAutoConfigure::lookupServer()
{
QDnsLookup *dnsLookup = new QDnsLookup(this);
connect(dnsLookup,SIGNAL(finished()),this,SLOT(handleServerResult()));
dnsLookup->setType(QDnsLookup::MX);
dnsLookup->setName(m_testDomain);
dnsLookup->lookup();
}
void MailAutoConfigure::handleServerResult()
{
QDnsLookup *dnsLookup = reinterpret_cast<QDnsLookup*>(sender());
if (dnsLookup->error() != QDnsLookup::NoError) {
qWarning("DNS lookup failed");
dnsLookup->deleteLater();
return;
}
QDnsMailExchangeRecord mxRecord = dnsLookup->mailExchangeRecords().at(0);
m_testDomain = mxRecord.exchange();
dnsLookup->deleteLater();
getServerName();
}
QString MailAutoConfigure::getChildNodeValue(QDomNode node, QString nodeName)
{
return node.namedItem(nodeName).firstChild().nodeValue();
}
void MailAutoConfigure::getServerInfo()
{
QDomDocument *confDocument = new QDomDocument("confInfo");
if (!confDocument->setContent(m_netReply->readAll())) {
qDebug() << "Could not set xml content";
return;
}
QDomNode inInfo;
QDomNodeList inServers = confDocument->elementsByTagName("incomingServer");
for(int i = 0; i < inServers.count(); i++) {
if(inServers.at(i).attributes().namedItem("type").nodeValue() == "imap") {
inInfo = inServers.at(i);
break;
}
}
QDomNodeList inElems = inInfo.childNodes();
for(int i = 0; i < inElems.count(); i++) {
if(!inElems.at(i).isComment()) {
qDebug() << inElems.at(i).nodeName() << inElems.at(i).firstChild().nodeValue();
m_confInfo->inSettings.setProperty(inElems.at(i).nodeName().toLatin1(),inElems.at(i).firstChild().nodeValue());
}
}
QDomNode outInfo = confDocument->elementsByTagName("outgoingServer").at(0);
QDomNodeList outElems = outInfo.childNodes();
for(int i = 0; i < outElems.count(); i++) {
if(!outElems.at(i).isComment()) {
qDebug() << outElems.at(i).nodeName() << outElems.at(i).firstChild().nodeValue();
m_confInfo->outSettings.setProperty(outElems.at(i).nodeName().toLatin1(),outElems.at(i).firstChild().nodeValue());
}
}
emit finished(m_confInfo);
}
#ifndef MAILAUTOCONFIGURE_H
#define MAILAUTOCONFIGURE_H
#include <QObject>
#include <QDnsLookup>
#include <QUrl>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDomDocument>
#include <QDomElement>
class SettingsObject : public QObject
{
Q_OBJECT
public:
QObject inSettings;
QObject outSettings;
};
class MailAutoConfigure : public QObject
{
Q_OBJECT
public:
explicit MailAutoConfigure(QObject *parent = 0, QString emailAddress = QString());
public slots:
void getConf();
signals:
void finished(SettingsObject*);
private slots:
void handleServerResult();
void fileExistsReply();
void getServerInfo();
private:
void getServerName();
void lookupServer();
QString stripSubdomain(QString dmn);
void networkFileExists(QUrl u);
QString getChildNodeValue(QDomNode node, QString nodeName);
SettingsObject *m_confInfo;
QString m_emailDomain;
bool m_isEmailDomain;
QNetworkReply *m_netReply;
QString m_testDomain;
};
#endif // MAILAUTOCONFIGURE_H