add autoconfig feature

This commit is contained in:
Peter Hormanns 2019-12-02 19:11:23 +01:00
parent ab32be694a
commit e084e04133
3 changed files with 167 additions and 1 deletions

View File

@ -44,6 +44,11 @@
<servlet-class>de.hsadmin.pillar.JsonPillarServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>AutoconfigServlet</servlet-name>
<servlet-class>de.hsadmin.autoconfig.AutoconfigAutodiscoverServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Queue Status Servlet</servlet-name>
<url-pattern>/queueStatus</url-pattern>
@ -54,6 +59,11 @@
<url-pattern>/pillar</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AutoconfigServlet</servlet-name>
<url-pattern>/config-v1.1.xml</url-pattern>
</servlet-mapping>
<!--
<servlet-mapping>
<servlet-name>Queue PacTasks Servlet</servlet-name>

View File

@ -0,0 +1,156 @@
package de.hsadmin.autoconfig;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.httpclient.HttpStatus;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import de.hsadmin.core.model.Transaction;
import de.hsadmin.core.util.IPv6Trick;
import de.hsadmin.mods.email.EMailAddress;
import de.hsadmin.mods.pac.Pac;
import de.hsadmin.mods.user.UnixUser;
public class AutoconfigAutodiscoverServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Thunderbird autoconfig
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
final String emailAddr = req.getParameter("emailaddress");
if (emailAddr == null || emailAddr.length() == 0) {
resp.sendError(HttpStatus.SC_UNAUTHORIZED);
return;
}
final String[] addrParts = emailAddr.split("@");
if (addrParts.length != 2) {
resp.sendError(HttpStatus.SC_BAD_REQUEST);
return;
}
final String localpart = addrParts[0];
final String domain = addrParts[1];
final Transaction transaction = new Transaction("autoconfig");
final EntityManager em = transaction.getEntityManager();
final Query emailQuery = em.createQuery("SELECT addr FROM EMailAddresses WHERE addr.localpart = :localpart AND addr.domain = :domain AND ( addr.subdomain IS NULL OR addr.subdomain = :subdomain)");
emailQuery.setParameter("subdomain", "");
emailQuery.setParameter("domain", domain);
emailQuery.setParameter("localpart", localpart);
final Object emailResult = emailQuery.getSingleResult();
if (emailResult == null) {
transaction.close();
resp.sendError(HttpStatus.SC_BAD_REQUEST);
return;
}
final EMailAddress emailAddress = (EMailAddress) emailResult;
final Query mboxQuery = em.createQuery("SELECT mbox FROM UnixUsers WHERE mbox.name = :target");
final String target = emailAddress.getTarget();
if (target == null || target.length() < 5 || (target.length() > 6 && target.charAt(5) != '-')) {
transaction.close();
resp.sendError(HttpStatus.SC_BAD_REQUEST);
return;
}
mboxQuery.setParameter("target", target);
final Object mboxResult = mboxQuery.getSingleResult();
if (mboxResult == null) {
transaction.close();
resp.sendError(HttpStatus.SC_BAD_REQUEST);
return;
}
final UnixUser mbox = (UnixUser) mboxResult;
final Pac pac = mbox.getPac();
final String pacDomain = pac.getName() + ".hostsharing.net";
final String userName = mbox.getName();
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.newDocument();
Element clientConfig = document.createElement("clientConfig");
clientConfig.setAttribute("version", "1.1");
document.appendChild(clientConfig);
Element emailProvider = appendElementWithAttribute(document, clientConfig, "emailProvider", "id", "hostsharing.net");
appendElementWithText(document, emailProvider, "domain", "hostsharing.net");
Element incomingServer = appendElementWithAttribute(document, emailProvider, "incomingServer", "type", "imap");
appendElementWithText(document, incomingServer, "hostname", pacDomain);
appendElementWithText(document, incomingServer, "port", "993");
appendElementWithText(document, incomingServer, "socketType", "SSL");
appendElementWithText(document, incomingServer, "username", userName);
appendElementWithText(document, incomingServer, "authentication", "password-cleartext");
Element outgoingServer = appendElementWithAttribute(document, emailProvider, "outgoingServer", "type", "smtp");
appendElementWithText(document, outgoingServer, "hostname", pacDomain);
appendElementWithText(document, outgoingServer, "port", "465");
appendElementWithText(document, outgoingServer, "socketType", "SSL");
appendElementWithText(document, outgoingServer, "username", userName);
appendElementWithText(document, outgoingServer, "authentication", "password-cleartext");
appendElementWithText(document, outgoingServer, "addThisServer", "true");
appendElementWithText(document, outgoingServer, "useGlobalPreferredServer", "true");
serializeDocument(document, resp);
} catch (DOMException e) {
throw new ServletException(e);
} catch (ParserConfigurationException e) {
throw new ServletException(e);
}
transaction.close();
}
/**
* Microsoft autodiscover
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
final String remoteAddr = req.getRemoteAddr();
if (!IPv6Trick.isKnownRemote(remoteAddr)) {
resp.sendError(HttpStatus.SC_UNAUTHORIZED);
return;
}
}
private Element appendElementWithAttribute(final Document document, final Element parent,
final String childElementName, final String attributeName, final String attributeValue) {
final Element child = document.createElement(childElementName);
child.setAttribute(attributeName, attributeValue);
parent.appendChild(child);
return child;
}
private Element appendElementWithText(final Document document, final Element parent,
final String childElementName, final String text) {
final Element child = document.createElement(childElementName);
parent.appendChild(child);
child.appendChild(document.createTextNode(text));
return child;
}
private void serializeDocument(final Document document, final HttpServletResponse resp)
throws ServletException {
resp.setContentType("text/xml");
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(resp.getOutputStream()));
} catch (TransformerException e) {
throw new ServletException(e);
} catch (IOException e) {
throw new ServletException(e);
}
}
}

View File

@ -137,7 +137,7 @@ public class JsonPillarServlet extends HttpServlet {
writer.println(" ]");
writer.println("}");
writer.close();
em.close();
transaction.close();
}
}