diff --git a/.env.example b/.env.example index ff75466..9b5e733 100644 --- a/.env.example +++ b/.env.example @@ -17,3 +17,8 @@ POSTMARK_API_KEY=your_postmark_server_token BTCPAY_URL=https://payment.nxtgroup.org FROM_EMAIL=billing@nxtgroup.org BCC_EMAIL=admin@nxtgroup.org,finance@nxtgroup.org + +# Test Postmark after deploy (docker exec or Portainer console): +# python app.py test-email you@example.com +# Or from host: +# curl -X POST "http://localhost:5000/test-email?token=YOUR_WEBHOOK_SECRET&to=you@example.com" diff --git a/app.py b/app.py index e1fd7c4..defd80f 100644 --- a/app.py +++ b/app.py @@ -58,6 +58,9 @@ def get_html_template(order_id, invoice_id, amount, currency, amount_paid, remai """ def send_postmark_email(to_email, subject, html_body): + if not POSTMARK_API_KEY: + return {"ok": False, "status_code": None, "error": "POSTMARK_API_KEY is not set"} + headers = { "Accept": "application/json", "Content-Type": "application/json", @@ -71,9 +74,18 @@ def send_postmark_email(to_email, subject, html_body): "HtmlBody": html_body, "MessageStream": "outbound" } - + response = requests.post("https://api.postmarkapp.com/email", json=payload, headers=headers) - return response.status_code == 200 + result = {"ok": response.status_code == 200, "status_code": response.status_code} + if not result["ok"]: + result["error"] = response.text + return result + + +def send_test_email(to_email): + html_body = get_html_template("TEST-001", "test-invoice-id", 100.0, "USD", 50.0, 50.0) + subject = "BTCPay Mailer test email" + return send_postmark_email(to_email, subject, html_body) @app.route('/btcpay-webhook', methods=['POST']) def btcpay_webhook(): @@ -120,14 +132,46 @@ def btcpay_webhook(): html_body = get_html_template(order_id, invoice_id, amount, currency, amount_paid, remaining) subject = f"Action Required: Partial payment received for Order #{order_id}" - email_sent = send_postmark_email(buyer_email, subject, html_body) - - if email_sent: + result = send_postmark_email(buyer_email, subject, html_body) + + if result["ok"]: return jsonify({"status": "success", "message": "Partial payment email sent"}), 200 - else: - return jsonify({"error": "Failed to send email via Postmark"}), 500 + return jsonify({"error": "Failed to send email via Postmark", "details": result}), 500 return jsonify({"status": "ignored", "reason": "Payment meets total or invoice not in New state"}), 200 + +@app.route('/test-email', methods=['POST']) +def test_email(): + token = request.args.get('token') + if token != WEBHOOK_SECRET: + return jsonify({"error": "Unauthorized"}), 401 + + to_email = request.args.get('to') or request.json.get('to') if request.is_json else None + if not to_email: + return jsonify({"error": "Missing 'to' email address"}), 400 + + result = send_test_email(to_email) + if result["ok"]: + return jsonify({ + "status": "success", + "message": f"Test email sent to {to_email}", + "from": FROM_EMAIL, + "bcc": BCC_EMAIL, + }), 200 + return jsonify({"error": "Failed to send test email via Postmark", "details": result}), 500 + + if __name__ == '__main__': + import sys + + if len(sys.argv) >= 3 and sys.argv[1] == 'test-email': + to = sys.argv[2] + outcome = send_test_email(to) + if outcome["ok"]: + print(f"OK: test email sent to {to} (from {FROM_EMAIL}, bcc {BCC_EMAIL})") + sys.exit(0) + print(f"FAIL: {outcome}", file=sys.stderr) + sys.exit(1) + app.run(host='0.0.0.0', port=5000) \ No newline at end of file