2010-08-25 3 views
2

Я разрабатываю приложение Google App Engine.
Я хочу получать письма в разделе «%username%@appid.appspotmail.com», где% username% принадлежит пользователю приложения.
Я просто не могу понять, что определить в файле web.xml.
Любое подобное решение, как письма в:приложение для обработки входящих сообщений

является приемлемым (если это облегчает использование подстановочных знаков).

Я пытался (как это было предложено Гопи)
отображение соответствующего сервлета к <url-pattern>/_ah/mail/user.*</url-pattern> в файле web.xml. Это не работает.
Клиент получает сообщение о отказе, тогда как журналы сервера отображают соответствующий запрос, полученный приложением, но отклоняются с помощью 404. No «Никакие обработчики не соответствуют этому URL-адресу». INFO добавляется в запись журнала. Кроме того, когда GETing сгенерированный URL-адрес, я не получаю «Эта страница не поддерживает GET», а просто 404.
Если я, однако, отправляю почту, чтобы сказать «[email protected]», журналы показывают 404 (которые они должны, поскольку они не отображаются в web.xml). Кроме того, для такого запроса «Нет обработчиков соответствовали этому URL-адресу». INFO добавляется в соответствующую запись в журнале.

Излишне говорить, что Входящая почта находится в разделе Конфигурированные услуги.

ответ

0

Ну ... После попытки каждого возможное решение/url-mapping, я пошел с быстрым и уродливым.
Суть заключается в том, чтобы иметь один «поймать все» почтовый сервлет, работать диспетчером для других, определенных сервлетов. Это как гигант switch, где параметр является URL-адресом запроса.
Это НЕ то, что я хотел, но он работает и, кажется, единственный, что делает.

У меня есть один сервлет IncomingMail, который обрабатывает ВСЕ входящую почту. период.
Итак, единственное отображение URL-адресов при /_ah/mail/ является следующее:

<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> 

Кроме того, у меня есть следующие сервлет, отображается как «набившие оскомину-сервлет»:
(обратите внимание <url-pattern>, не "ПОЧТА отображается" сервлет)

<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> 

улов-все сервлет (в конечном счете) выглядит как гигантский переключатель:

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); 
     }   

    } 
} 

Целевой сервлет (GetUserMail в этом случае), делает getRequestParameter("email"), чтобы увидеть конкретный выделенный почтовый ящик.
Он получит все письма, отправленные на «user.%un%@appid.appspotmail.com», где% un% является именем пользователя в прикладном пространстве.
Параметр электронной почты, полученный сервлетом, будет иметь форму «%un%@appid.appspotmail.com» без проницательного префикса.
Каждый такой «конкретный» сервлет, получивший «отрезание» от сервлета почтового диспетчера, с параметром электронной почты уже без проницательного префикса.

Одно примечание я добавлю под залог:
Если вы обеспокоены фиктивных запросов к «конкретным сервлетов», просто определить их все под общим виртуальным пространством имен говорят /servmail/ на вашем сайте, и определить новый <security-constraint> к разрешить запросы инициироваться только внутри самого приложения.
Подобно (внутри 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> 

еще хотелось бы услышать от кого-то испытанной и удалось при этом почтовое отображение подстановочные <url-pattern>, кроме броской всего один.

0

Я думаю положить запись, подобную ниже в ваш web.xml должна работать, чтобы соответствовать вашему второго случаю'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> 
+0

Это сообщение рикошета на стороне клиента, и 404 на логах сервера. Как ни странно, я не получаю «Нет обработчиков, соответствующих этому URL». Кроме того, я вижу, что запрос возник изнутри механизма самодвижения сервера по его IP: 0.1.0.20. – David

+0

*** журнальной записи *** # 1. 08-25 3:25 вечера 40,743 /_ah/mail/[email protected] 404 19cpu_ms 0kb 13 мс Подробнее 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

2

Ниже приводится plausable объяснение, благодаря url-pattern and wildcards , который относится к http://jcp.org/aboutJava/communityprocess/mrel/jsr154/index2.html (выберите раздел 11.2)

В URL-шаблон символ * ведет себя по-разному, чтобы как можно было бы предположить, это обрабатывается как нормальный символ, за исключением , - когда строка заканчивается на/* для «сопоставления пути» или она начинается с *. для «картирования расширения»

Слишком плохо, было бы хорошо, чтобы адреса получателей адресов подписи под шаблоном к различным сервлетам, как показано в образцах API API Google. Сейчас я использую абсолютные совпадения, которые не так чисты, как нужно добавить приложение.

0

У меня был аналогичная проблема (с помощью Python, так YAML конфигурационных файлов, а не XML), и причина оказалась потому, что я поставил:

- url: /_ah/mail/.+ 
    script: handle_incoming_email.py 
    login: admin 

перед существующими броскими всеми записями:

- url: /.* 
    script: main.py 

Это дало 404s на сервере и «Ошибка отправки сообщения» при отправке тестовых сообщений.

Перемещение его после входа в ловушку разрешило проблему.

0

Я уверен, что проблема в том, что вы пытаетесь использовать .*. Выражения URL в web.xml - это глобусы, а не регулярные выражения, поэтому вместо этого следует использовать только * - .* будет соответствовать только строкам, начиная с точки.

3

Это изменение произошло, когда App Engine начал использовать настоящий веб-сервер Java (и поэтому объяснение Тоби на месте ... к сожалению, я не могу восстановить свой логин, чтобы его проголосовать!). Моя рекомендация - использовать фильтр. Я играл с фильтром ниже при написании игрушечного приложения для GAE. После того, как вы определили базовый класс в конце этого сообщения, вы можете создать серию почтовых обработчиков (например, следующее). Все, что вам нужно сделать, это зарегистрировать каждый фильтр в вашем web.xml для обработки/_ah/mail/*.

public class HandleDiscussionEmail extends MailHandlerBase { 

    public HandleDiscussionEmail() { super("discuss-(.*)@(.*)"); } 

    @Override 
    protected boolean processMessage(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException 
    { 
    MimeMessage msg = getMessageFromRequest(req); 
    Matcher match = getMatcherFromRequest(req); 
    ... 
} 

} 

public abstract class MailHandlerBase implements Filter { 

    private Pattern pattern = null; 

    protected MailHandlerBase(String pattern) { 
    if (pattern == null || pattern.trim().length() == 0) 
    { 
     throw new IllegalArgumentException("Expected non-empty regular expression"); 
    } 
    this.pattern = Pattern.compile("/_ah/mail/"+pattern); 
    } 

    @Override public void init(FilterConfig config) throws ServletException { } 

    @Override public void destroy() { } 

    /** 
    * Process the message. A message will only be passed to this method 
    * if the servletPath of the message (typically the recipient for 
    * appengine) satisfies the pattern passed to the constructor. If 
    * the implementation returns <code>false</code>, control is passed 
    * o the next filter in the chain. If the implementation returns 
    * <code>true</code>, the filter chain is terminated. 
    * 
    * The Matcher for the pattern can be retrieved via 
    * getMatcherFromRequest (e.g. if groups are used in the pattern). 
    */ 
    protected abstract boolean processMessage(HttpServletRequest req, HttpServletResponse res) throws ServletException; 

    @Override 
    public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain chain) 
     throws IOException, ServletException { 

    HttpServletRequest req = (HttpServletRequest) sreq; 
    HttpServletResponse res = (HttpServletResponse) sres; 

    MimeMessage message = getMessageFromRequest(req); 
    Matcher m = applyPattern(req); 

    if (m != null && processMessage(req, res)) { 
     return; 
    } 

    chain.doFilter(req, res); // Try the next one 

    } 

    private Matcher applyPattern(HttpServletRequest req) { 
    Matcher m = pattern.matcher(req.getServletPath()); 
    if (!m.matches()) m = null; 

    req.setAttribute("matcher", m); 
    return m; 
    } 

    protected Matcher getMatcherFromRequest(ServletRequest req) { 
    return (Matcher) req.getAttribute("matcher"); 
    } 

    protected MimeMessage getMessageFromRequest(ServletRequest req) throws ServletException { 
    MimeMessage message = (MimeMessage) req.getAttribute("mimeMessage"); 
    if (message == null) { 
     try { 
     Properties props = new Properties(); 
     Session session = Session.getDefaultInstance(props, null); 
     message = new MimeMessage(session, req.getInputStream()); 
     req.setAttribute("mimeMessage", message); 

     } catch (MessagingException e) { 
     throw new ServletException("Error processing inbound message", e); 
     } catch (IOException e) { 
     throw new ServletException("Error processing inbound message", e); 
     } 
    } 
    return message; 
    } 



} 
Смежные вопросы