Quando o servidor de e-mail diz não
Tradução automática
Esta página foi traduzida automaticamente do inglês e ainda não foi revisada por um falante nativo; correções são bem-vindas no GitHub. Se algo não bater, vale o original em inglês. O código e os resultados são os mesmos do original, importados dos arquivos testados.
Tarefa: um pedido precisa ser salvo mesmo quando o e-mail de confirmação não pode ser enviado — e o visitante deve ficar sabendo, não receber uma página de erro.
Por padrão, um q:mail que o servidor não aceita interrompe a ação com o motivo do servidor. onerror="continue" deixa a ação seguir e coloca o resultado em <name>_result: success, e error.message quando falhou. Esta receita aponta para um servidor de e-mail que não existe, então toda mensagem falha — como acontece quando o servidor de verdade está fora do ar:
# Recipe: an order is saved even when the confirmation e-mail cannot be sent.
# The mail server here is deliberately unreachable (nothing listens on port 9),
# so every q:mail fails — as it does when the real server is down.
paths:
components: ./components
migrations: ./migrations
datasources:
db:
driver: sqlite
database: ./data/orders.db
mail:
host: 127.0.0.1
port: 9
tls: false
timeout: 2
from: shop@example.comCREATE TABLE orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL,
item TEXT NOT NULL
);<q:component name="Order">
<q:action name="order" method="POST">
<q:param name="email" type="email" required="true" />
<q:param name="item" required="true" />
<q:query name="saved" datasource="db">
INSERT INTO orders (email, item) VALUES (:email, :item)
<q:param name="email" value="{email}" type="string" />
<q:param name="item" value="{item}" type="string" />
</q:query>
<!-- onerror="continue": a refused message does not undo the order -->
<q:mail name="confirmation" to="{email}" subject="Your order: {item}"
type="text" onerror="continue">We received your order for {item}.</q:mail>
<q:if condition="confirmation_result.success">
<q:redirect url="/" flash="Ordered {item}. A confirmation is on its way." />
</q:if>
<q:redirect url="/" flash="Ordered {item}. We could not send the confirmation e-mail." />
</q:action>
<h1>Order</h1>
<q:if condition="flash"><p class="flash">{flash}</p></q:if>
<form method="POST" action="/?action=order">
<input name="email" type="email" />
<input name="item" />
<button>Order</button>
</form>
</q:component>O pedido é inserido antes do e-mail, e a mensagem flash diz o que aconteceu. O teste confere as duas coisas — a linha está lá, e o visitante foi avisado:
<q:test name="the order is saved and the visitor told the e-mail failed" page="/">
<test:submit action="order" email="ana@example.com" item="Blue mug" />
<test:expect redirect="/" flash="Ordered Blue mug. We could not send the confirmation e-mail." />
<test:expect table="orders" count="1" where="email = 'ana@example.com' AND item = 'Blue mug'" />
</q:test>tests/order.test.q
PASS the order is saved and the visitor told the e-mail failed
1 passed, 0 failedEm desenvolvimento, host: log evita a falha por completo; onerror="continue" é para o dia em que o servidor de verdade estiver fora do ar. Mais em Files & Mail (em inglês).
Testado: esta página importa os arquivos de examples/cookbook/files-and-mail/mail-server-refuses/, e o resultado acima saiu de rodá-los.