views:

46

answers:

2

I am developing a Google App Engine application.
I wish to receive mails under '%username%@appid.appspotmail.com', where %username% belongs to a user of the application.
I just can't figure out what to define in web.xml file.
Any similar solution such as mails to:

is acceptable (if it makes it easier with the wildcards).

I've tried (as suggested by Gopi)
mapping the relevant servlet to <url-pattern>/_ah/mail/user.*</url-pattern> within the web.xml file. It's not working.
The client gets a bounce message, whereas the server logs, do show a relevant request received by the app, but rejected with a 404. No "No handlers matched this URL." INFO is added to the log entry. In addition, when GETing the generated URL, I don't get a 'This page does not support GET', but rather a plain 404.
If I however send mail to say '[email protected]', the logs show a 404 (which they should, as it's not mapped in the web.xml). In addition, for such a request, a "No handlers matched this URL." INFO is added to the relevant log entry.

Needless to say that, Incoming mail IS found under Configured Services.

A: 

I think putting an entry similar to below into your web.xml should work to match your second case 'usermailbox.%username%@appid.appspotmail.com

<servlet>
  <servlet-name>handlemail</servlet-name>
  <servlet-class>HandleMyMail</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>handlemail</servlet-name>
  <url-pattern>/_ah/mail/usermailbox.*</url-pattern>
</servlet-mapping>
Gopi
It's a bounce message on the client side, and a 404 on the server logs.Strangely enough I don't get a "No handlers matched this URL.".In addition you I see that the request originated from within the server self-forward mechanism by its IP: 0.1.0.20.
David
***THE LOG ENTRY***# 1. 08-25 03:25PM 40.743 /_ah/mail/[email protected] 404 13ms 19cpu_ms 0kb See details 0.1.0.20 - - [25/Aug/2010:15:25:40 -0700] "POST /_ah/mail/[email protected] HTTP/1.1" 404 234 - - "appid.appspot.com" ms=13 cpu_ms=19 api_cpu_ms=0 cpm_usd=0.000947
David
A: 

Well... After trying every possible solution/url-mapping, I went with fast and ugly one.
The gist is to have a single "catch all" mail servlet, to work as a dispatcher to other, specific, servlets. It's like a giant switch, where the parameter is the request URL.
This is NOT what I wished for, but it works, and seems to be the only one that does.

I have a single servlet IncomingMail that handles ALL incoming mail. period.
So now, the only mapping of URLs under /_ah/mail/ is the following:

<servlet>
    <servlet-name>IncomingMail</servlet-name>
    <servlet-class>IncomingMail</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>IncomingMail</servlet-name>
    <url-pattern>/_ah/mail/*</url-pattern>
</servlet-mapping>

In addition, I have the following servlet, mapped as a "plain-old-servlet":
(notice the <url-pattern>, not a "mail mapped" servlet)

<servlet>
    <servlet-name>GetUserMail</servlet-name>
    <servlet-class>GetUserMail</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>GetUserMail</servlet-name>
    <url-pattern>/serv/userMail</url-pattern>
</servlet-mapping>

The catch-all servlet (would eventually) look like a giant switch:

public class IncomingMail extends HttpServlet {
    private final String USER_MAIL_PREFIX="http://appid.appspot.com/_ah/mail/user.";
    private final String USER_MAIL_SERVLET="/serv/userMail";
    ...
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String url = req.getRequestURL().toString();
        System.out.println("IncomingMail called, with URL: "+url);
        String email;
        String servlet;

        if (url.startsWith(USER_MAIL_PREFIX)) {
            email=url.replace(USER_MAIL_PREFIX, "");
            servlet=USER_MAIL_SERVLET;
        }//userMail 
        if (url.startsWith(OTHER_PREFIX)) {
            //Redirect to OTHER servlet
        }
        ...
        System.out.println("forward to '"+servlet+"', with email '"+email+"'");
        RequestDispatcher dispatcher=req.getRequestDispatcher(servlet);
        try {
            req.setAttribute("email", email);
            dispatcher.forward(req, resp);
        } catch (ServletException e) {              
            System.err.println(e);
        }           

    }
}

The destination servlet (GetUserMail in this case), does a getRequestParameter("email"), to see the specific destined mailbox.
It will receive all mails sent to 'user.%un%@appid.appspotmail.com', where %un% is a username in the application space.
The email parameter received by the servlet would be of the form '%un%@appid.appspotmail.com', without the discerning prefix.
Each such "specific" servlet, would get "its cut" from the mail dispatcher servlet, with the email parameter already without the discerning prefix.

One note I will add under security:
If you're worried of bogus requests to the "specific servlets", just define them all under a common virtual namespace say /servmail/ in your site, and define a new <security-constraint> to allow requests to originate only within the application itself.
Like so (inside web.xml):

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>MailServlets</web-resource-name>
            <description>policy for specific mail servlets</description>
            <url-pattern>/servmail/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

Would still love to hear from someone that tried and succeeded in doing a wildcard <url-pattern> mail mapping, other than a catch-all one.

David