The webhooks of the ingresses (Letterbox.Ingress), a route of the
app's own router. mix letterbox.install writes one for every
ingress, the ingress named by the path:
scope "/inbound" do
pipe_through :webhooks
post "/webhooks/:ingress", Letterbox.Plug, []
endThe path, the scope and the pipeline are the app's to change: nothing in Letterbox depends on them. A route can also name its ingress, one route for each, at any path:
post "/mail/resend", Letterbox.Plug, ingress: :resend
post "/hooks/postfix", Letterbox.Plug, ingress: :relayThe ingress is the route's :ingress option, else the :ingress
parameter of its path. In an app without Phoenix's router, it is a Plug
like any other (forward "/inbound/resend", Letterbox.Plug, ingress: :resend).
It answers:
204- the request was the ingress's, and what it brought is kept (or, for an email to fetch, noted): the provider stops sending it. Again for a message already kept.401- it was not the ingress's (verify/3refused it).404- no ingress of that name.413- the body is larger than:max_bytes(Letterbox.Config).422- the ingress could not read it.500- it could not be kept (the store, the database): the provider sends it again later.
The route takes no session and no CSRF token: a provider has neither.
Its pipeline must not have :protect_from_forgery.
A signed webhook needs its body as it was sent: the plug declares it
(use PhoenixMountable.RawBody), and the endpoint's Plug.Parsers
keeps it with body_reader: {PhoenixMountable.RawBody, :read_body, [MyAppWeb.Router]}, which mix letterbox.install adds. A relay's raw
email (message/rfc822) is passed by the parsers unread, and needs no
copy.