I have a simple contact form on a website for my sister’s businsess, all running on Biff, set up with Postmark, following the old tutorial. It seems to work for me when I test it myself. And she does receive emails from the site periodically. But she has had reports from a handfull of her clients that they cannot send email. (when they press send, nothing happens). Where would i begin to troubleshoot this?)
I am on an older version
https://github.com/jacobobryant/biff/commit/821182173945d40cde59cbd1784fc32bb5b0d4e0 But will be upgrading it..
I do have PaperTrail set up. Looking at that now
hm. First I'd check the logs in Postmark to see if there are any failed sends / if you see anything when searching for one of the clients' email addresses (the ones where it didn't work).
I wouldn't worry about upgrading biff; it shouldn't make a difference.
it is odd that it works some of the time. If it didn't work at all I'd say perhaps it's a recaptcha misconfiguration.
Maybe try it in safari/ios if you haven't already? That's bit me sometimes since I don't use a mac or iphone. usually just CSS stuff though.
But yeah, if all else fails might just need to set up more logging and see if you see anything. To get client logs, you could set up an endpoint on your backend that takes a post request and just prints out the contents, which will make it get sent to papertrail. Then you can make a log() js function that takes a string and sends it to that endpoint, and sprinkle a few log() calls around. There's probably more fancy stuff you could do.
if there are multiple forms on the site, of course make sure to test them all--maybe just one of the forms is set up wrong.
Thanks, digesting this. The Postmark logs for 45 days only shows “processed” and “delivered” events
Should I change this out for MailerSend?
probably fine on the email delivery side then. (I'd delete that screenshot so the emails aren't made public).
I wouldn't switch to mailersend just for this, I'm guessing the emails aren't being sent in the first place for some reason.
Yes, your right. Deleted
Here’s a sample of the continuous errors I’m getting in my log.. (not necessarily email related?)
Aug 27 00:01:04 groundedsol sshd error: kex_exchange_identification: banner line contains invalid characters
Aug 27 00:38:32 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 01:12:43 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 01:15:37 groundedsol sshd error: kex_exchange_identification: banner line contains invalid characters
Aug 27 01:54:11 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 01:57:08 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET / HTTP/1.1"
Aug 27 02:21:34 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET /admin/console/index.html HTTP/1.1"
Aug 27 02:21:35 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET /admin/console/index.html HTTP/1.1"
Aug 27 02:21:35 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET /covenantuser/login HTTP/1.1"
Aug 27 02:21:37 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET /covenantuser/login HTTP/1.1"
Aug 27 02:21:44 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET /new/login HTTP/1.1"
Aug 27 02:21:45 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET /new/login HTTP/1.1"
Aug 27 02:21:45 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET / HTTP/1.1"
Aug 27 02:21:46 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET / HTTP/1.1"
Aug 27 02:21:47 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET /login HTTP/1.1"
Aug 27 02:21:48 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET /login HTTP/1.1"
Aug 27 02:21:50 groundedsol sshd error: kex_exchange_identification: banner line contains invalid characters
Aug 27 02:30:53 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 02:40:00 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 02:51:19 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 03:10:24 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 03:39:19 groundedsol sshd error: kex_exchange_identification: banner line contains invalid characters
Aug 27 03:55:37 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 04:14:53 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 04:21:52 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 04:30:48 groundedsol sshd error: maximum authentication attempts exceeded for root from 197.205.84.71 port 45062 ssh2 [preauth]
Aug 27 04:53:57 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 05:49:35 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 06:33:45 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 06:47:18 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 07:26:37 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 07:54:02 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 07:57:45 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 08:56:13 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 09:11:39 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 09:42:15 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET / HTTP/1.1"
Aug 27 09:42:16 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET / HTTP/1.1"
Aug 27 09:50:20 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "GET / HTTP/1.1"
Aug 27 10:39:47 groundedsol sshd error: kex_exchange_identification: client sent invalid protocol identifier "MGLNDD_165.227.202.216_22"
Aug 27 10:55:41 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 11:09:41 groundedsol sshd error: kex_exchange_identification: banner line contains invalid characters
Aug 27 11:46:23 groundedsol sshd error: kex_exchange_identification: banner line contains invalid characters
Aug 27 11:46:42 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 11:46:43 groundedsol sshd error: Protocol major versions differ: 2 vs. 1
Aug 27 11:52:20 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 12:11:45 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 12:23:00 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 12:28:14 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 12:46:46 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 12:47:28 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 12:51:14 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 13:02:43 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 13:13:24 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 13:47:15 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 14:51:34 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 15:09:23 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 15:20:27 groundedsol sshd error: kex_exchange_identification: banner line contains invalid characters
Aug 27 15:52:16 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 16:56:13 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 17:20:18 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 17:48:27 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 18:53:38 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 19:44:47 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 20:46:11 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 21:13:54 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 21:43:21 groundedsol sh [qtp903438105-109] INFO com.biffweb.impl.middleware - 3ms 404 get /404error-test-page-by-atoz-seo-tools
Aug 27 22:51:10 groundedsol sshd error: maximum authentication attempts exceeded for root from 59.11.153.178 port 60378 ssh2 [preauth]
Aug 27 22:51:13 groundedsol sshd error: maximum authentication attempts exceeded for root from 59.11.153.178 port 60952 ssh2 [preauth]
Aug 27 22:51:16 groundedsol sshd error: maximum authentication attempts exceeded for root from 59.11.153.178 port 33314 ssh2 [preauth]
Aug 27 22:51:22 groundedsol sshd error: maximum authentication attempts exceeded for invalid user admin from 59.11.153.178 port 34312 ssh2 [preauth]
Aug 27 22:51:25 groundedsol sshd error: maximum authentication attempts exceeded for invalid user admin from 59.11.153.178 port 34946 ssh2 [preauth]
Aug 27 22:51:31 groundedsol sshd error: maximum authentication attempts exceeded for invalid user oracle from 59.11.153.178 port 35998 ssh2 [preauth]
Aug 27 22:51:34 groundedsol sshd error: maximum authentication attempts exceeded for invalid user oracle from 59.11.153.178 port 36610 ssh2 [preauth]
Aug 27 22:51:39 groundedsol sshd error: maximum authentication attempts exceeded for invalid user usuario from 59.11.153.178 port 37706 ssh2 [preauth]
Aug 27 22:51:42 groundedsol sshd error: maximum authentication attempts exceeded for invalid user usuario from 59.11.153.178 port 38278 ssh2 [preauth]
Aug 27 22:51:49 groundedsol sshd error: maximum authentication attempts exceeded for invalid user test from 59.11.153.178 port 39454 ssh2 [preauth]
Aug 27 22:51:52 groundedsol sshd error: maximum authentication attempts exceeded for invalid user test from 59.11.153.178 port 40080 ssh2 [preauth]
Aug 27 22:51:55 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
Aug 27 22:51:57 groundedsol sshd error: maximum authentication attempts exceeded for invalid user user from 59.11.153.178 port 41202 ssh2 [preauth]
Aug 27 22:52:00 groundedsol sshd error: maximum authentication attempts exceeded for invalid user user from 59.11.153.178 port 41832 ssh2 [preauth]
Aug 27 22:52:06 groundedsol sshd error: maximum authentication attempts exceeded for invalid user ftpuser from 59.11.153.178 port 42882 ssh2 [preauth]
Aug 27 22:52:09 groundedsol sshd error: maximum authentication attempts exceeded for invalid user ftpuser from 59.11.153.178 port 43504 ssh2 [preauth]
Aug 27 22:52:15 groundedsol sshd error: maximum authentication attempts exceeded for invalid user test1 from 59.11.153.178 port 44656 ssh2 [preauth]
Aug 27 22:52:18 groundedsol sshd error: maximum authentication attempts exceeded for invalid user test1 from 59.11.153.178 port 45278 ssh2 [preauth]
Aug 27 22:52:24 groundedsol sshd error: maximum authentication attempts exceeded for invalid user test2 from 59.11.153.178 port 46488 ssh2 [preauth]
Aug 27 22:52:27 groundedsol sshd error: maximum authentication attempts exceeded for invalid user test2 from 59.11.153.178 port 47080 ssh2 [preauth]
Aug 27 22:52:36 groundedsol sshd error: maximum authentication attempts exceeded for invalid user ubuntu from 59.11.153.178 port 48754 ssh2 [preauth]
Aug 27 22:52:39 groundedsol sshd error: maximum authentication attempts exceeded for invalid user ubuntu from 59.11.153.178 port 49338 ssh2 [preauth]
Aug 27 22:58:31 groundedsol sshd error: kex_exchange_identification: Connection closed by remote host
Aug 27 23:54:35 groundedsol sshd error: kex_exchange_identification: read: Connection reset by peer
probably can just ignore that/any other random-looking stuff in the logs; it's normal to get a bunch of requests from bots. That particular ip is from korea for example: https://whatismyipaddress.com/ip/59.11.153.178
Ok, just to validate that… Here’s a complete sample of log. (not filtered for “error”)
Aug 28 17:37:59 groundedsol sh [qtp903438105-140] INFO com.biffweb.impl.middleware - 7ms 200 get /
Aug 28 17:38:07 groundedsol kernel [20311047.970962] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=79.110.62.149 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=245 ID=13621 PROTO=TCP SPT=56393 DPT=22222 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:38:11 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 41480 [preauth]
Aug 28 17:38:28 groundedsol kernel [20311068.781986] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=162.142.125.89 DST=165.227.202.216 LEN=60 TOS=0x00 PREC=0x00 TTL=57 ID=4361 PROTO=TCP SPT=52388 DPT=10252 WINDOW=42340 RES=0x00 SYN URGP=0
Aug 28 17:38:40 groundedsol sshd Invalid user minecraft from 137.184.149.66 port 47220
Aug 28 17:38:40 groundedsol sshd Connection closed by invalid user minecraft 137.184.149.66 port 47220 [preauth]
Aug 28 17:38:46 groundedsol kernel [20311087.277796] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=192.155.81.124 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=242 ID=54321 PROTO=TCP SPT=38842 DPT=123 WINDOW=65535 RES=0x00 SYN URGP=0
Aug 28 17:38:59 groundedsol sh [qtp903438105-136] INFO com.biffweb.impl.middleware - 5ms 200 get /
Aug 28 17:39:12 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 35368 [preauth]
Aug 28 17:39:13 groundedsol sh [qtp903438105-142] INFO com.biffweb.impl.middleware - 8ms 200 get /
Aug 28 17:39:13 groundedsol sh [qtp903438105-140] INFO com.biffweb.impl.middleware - 3ms 404 get /.env
Aug 28 17:39:13 groundedsol sh [qtp903438105-133] INFO com.biffweb.impl.middleware - 3ms 405 post /
Aug 28 17:39:14 groundedsol kernel [20311114.408026] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=45.56.85.254 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=242 ID=54321 PROTO=TCP SPT=47827 DPT=49152 WINDOW=65535 RES=0x00 SYN URGP=0
Aug 28 17:39:27 groundedsol kernel [20311127.682055] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=167.94.138.150 DST=165.227.202.216 LEN=60 TOS=0x00 PREC=0x00 TTL=53 ID=61446 PROTO=TCP SPT=35930 DPT=3306 WINDOW=42340 RES=0x00 SYN URGP=0
Aug 28 17:39:43 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 54062 [preauth]
Aug 28 17:39:55 groundedsol kernel [20311155.990875] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=170.187.165.218 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=246 ID=54321 PROTO=TCP SPT=54080 DPT=40000 WINDOW=65535 RES=0x00 SYN URGP=0
Aug 28 17:39:59 groundedsol sh [qtp903438105-136] INFO com.biffweb.impl.middleware - 6ms 200 get /
Aug 28 17:40:09 groundedsol kernel [20311169.723388] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=185.224.128.59 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=242 ID=54321 PROTO=TCP SPT=60845 DPT=8080 WINDOW=65535 RES=0x00 SYN URGP=0
Aug 28 17:40:13 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 46588 [preauth]
Aug 28 17:40:38 groundedsol kernel [20311198.589724] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=143.42.1.191 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=246 ID=54321 PROTO=TCP SPT=43402 DPT=8007 WINDOW=65535 RES=0x00 SYN URGP=0
Aug 28 17:40:42 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 50002 [preauth]
Aug 28 17:40:44 groundedsol sh [qtp903438105-142] INFO com.biffweb.impl.middleware - 7ms 200 get /
Aug 28 17:40:59 groundedsol sh [qtp903438105-140] INFO com.biffweb.impl.middleware - 9ms 200 get /
Aug 28 17:41:09 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 41196 [preauth]
Aug 28 17:41:10 groundedsol kernel [20311230.603260] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=94.102.49.119 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=245 ID=30722 PROTO=TCP SPT=40001 DPT=3389 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:41:18 groundedsol kernel [20311238.483527] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=222.153.120.42 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=50 ID=19891 PROTO=TCP SPT=6287 DPT=23 WINDOW=919 RES=0x00 SYN URGP=0
Aug 28 17:41:28 groundedsol kernel [20311248.642686] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=148.135.35.230 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=243 ID=18926 PROTO=TCP SPT=47406 DPT=5800 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:41:39 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 48202 [preauth]
Aug 28 17:41:59 groundedsol sh [qtp903438105-135] INFO com.biffweb.impl.middleware - 6ms 200 get /
Aug 28 17:42:03 groundedsol kernel [20311284.156387] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=79.110.62.197 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=245 ID=17834 PROTO=TCP SPT=56326 DPT=11289 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:42:08 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 55608 [preauth]
Aug 28 17:42:19 groundedsol kernel [20311300.038144] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=95.214.27.14 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=244 ID=54321 PROTO=TCP SPT=49984 DPT=8081 WINDOW=65535 RES=0x00 SYN URGP=0
Aug 28 17:42:38 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 35536 [preauth]
Aug 28 17:42:57 groundedsol kernel [20311337.624323] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=79.110.62.194 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=245 ID=23702 PROTO=TCP SPT=55003 DPT=10400 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:42:57 groundedsol kernel [20311337.847749] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=79.110.62.210 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=245 ID=24394 PROTO=TCP SPT=55170 DPT=10689 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:42:58 groundedsol sh [qtp903438105-133] INFO com.biffweb.impl.middleware - 6ms 200 get /
Aug 28 17:42:59 groundedsol sh [qtp903438105-141] INFO com.biffweb.impl.middleware - 7ms 200 get /
Aug 28 17:43:08 groundedsol sshd Invalid user debian from 137.184.149.66 port 46626
Aug 28 17:43:08 groundedsol sshd Connection closed by invalid user debian 137.184.149.66 port 46626 [preauth]
Aug 28 17:43:13 groundedsol kernel [20311354.191013] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=45.156.129.54 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=245 ID=44175 PROTO=TCP SPT=18928 DPT=4433 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:43:38 groundedsol sshd Invalid user station2 from 137.184.149.66 port 40084
Aug 28 17:43:38 groundedsol sshd Connection closed by invalid user station2 137.184.149.66 port 40084 [preauth]
Aug 28 17:43:42 groundedsol kernel [20311382.922820] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=162.216.150.169 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x60 TTL=249 ID=54321 PROTO=TCP SPT=56512 DPT=1800 WINDOW=65535 RES=0x00 SYN URGP=0
Aug 28 17:43:43 groundedsol kernel [20311384.138593] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=45.33.112.95 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=239 ID=55388 PROTO=TCP SPT=60000 DPT=555 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:43:59 groundedsol sh [qtp903438105-142] INFO com.biffweb.impl.middleware - 9ms 200 get /
Aug 28 17:44:08 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 52140 [preauth]
Aug 28 17:44:33 groundedsol kernel [20311433.583625] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=89.248.163.205 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=245 ID=39190 PROTO=TCP SPT=49724 DPT=54321 WINDOW=1025 RES=0x00 SYN URGP=0
Aug 28 17:44:34 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 59286 [preauth]
Aug 28 17:44:59 groundedsol sh [qtp903438105-140] INFO com.biffweb.impl.middleware - 12ms 200 get /
Aug 28 17:45:03 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 52658 [preauth]
Aug 28 17:45:05 groundedsol kernel [20311466.000092] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=194.26.135.211 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=241 ID=23468 PROTO=TCP SPT=41393 DPT=4526 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:45:07 groundedsol kernel [20311467.791256] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=182.38.237.61 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=46 ID=10563 PROTO=TCP SPT=38897 DPT=23 WINDOW=57481 RES=0x00 SYN URGP=0
Aug 28 17:45:18 groundedsol sh [qtp903438105-133] INFO com.biffweb.impl.middleware - 7ms 200 get /
Aug 28 17:45:19 groundedsol kernel [20311479.426169] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=148.135.35.230 DST=165.227.202.216 LEN=40 TOS=0x00 PREC=0x00 TTL=243 ID=30325 PROTO=TCP SPT=47406 DPT=32774 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:45:22 groundedsol sh [qtp903438105-141] INFO com.biffweb.impl.middleware - 12ms 200 get /
Aug 28 17:45:23 groundedsol sh [qtp903438105-135] INFO com.biffweb.impl.middleware - 0ms 200 get /safari-pinned-tab.svg
Aug 28 17:45:26 groundedsol sh [qtp903438105-142] INFO com.biffweb.impl.middleware - 0ms 200 get /favicon-32x32.png
Aug 28 17:45:29 groundedsol sh [qtp903438105-133] INFO com.biffweb.impl.middleware - 0ms 200 get /favicon-16x16.png
Aug 28 17:45:32 groundedsol kernel [20311492.542417] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=80.66.83.225 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=246 ID=49575 PROTO=TCP SPT=27593 DPT=3306 WINDOW=1025 RES=0x00 SYN URGP=0
Aug 28 17:45:33 groundedsol sh [qtp903438105-141] INFO com.biffweb.impl.middleware - 0ms 200 get /favicon.ico
Aug 28 17:45:33 groundedsol sshd Invalid user maint from 137.184.149.66 port 37030
Aug 28 17:45:33 groundedsol sshd Connection closed by invalid user maint 137.184.149.66 port 37030 [preauth]
Aug 28 17:45:37 groundedsol sh [qtp903438105-135] INFO com.biffweb.impl.middleware - 0ms 200 get /apple-touch-icon.png
Aug 28 17:45:59 groundedsol sh [qtp903438105-142] INFO com.biffweb.impl.middleware - 25ms 200 get /
Aug 28 17:46:03 groundedsol sshd Invalid user csm from 137.184.149.66 port 57758
Aug 28 17:46:04 groundedsol sshd Connection closed by invalid user csm 137.184.149.66 port 57758 [preauth]
Aug 28 17:46:11 groundedsol kernel [20311531.927969] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=35.203.210.47 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=58 ID=5388 PROTO=TCP SPT=51237 DPT=2407 WINDOW=1024 RES=0x00 SYN URGP=0
Aug 28 17:46:17 groundedsol kernel [20311537.911970] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=185.165.191.27 DST=165.227.202.216 LEN=42 TOS=0x00 PREC=0x00 TTL=114 ID=29178 PROTO=UDP SPT=3672 DPT=3671 LEN=22
Aug 28 17:46:24 groundedsol kernel [20311544.972596] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 SRC=89.248.163.34 DST=165.227.202.216 LEN=44 TOS=0x00 PREC=0x00 TTL=246 ID=32414 PROTO=TCP SPT=57849 DPT=14124 WINDOW=1025 RES=0x00 SYN URGP=0
Aug 28 17:46:27 groundedsol sh [qtp903438105-133] INFO com.biffweb.impl.middleware - 0ms 200 get /img/gallery/thumb/Bees-guarding-flower-0124.jpg
Aug 28 17:46:33 groundedsol sshd Connection closed by authenticating user root 137.184.149.66 port 34128 [preauth]
Aug 28 17:46:49 groundedsol kernel [20311569.687596] [UFW BLOCK] IN=eth0 OUT= MAC=52:c2:eb:27:d6:9c:fe:00:00:00:01:01:08:00 yeah, not seeing anything surprising. I'd search for the endpoint that the form POSTs to. First thing I'd try to figure out is if the problem happens on the backend, or if it's on the frontend and the POST request never even comes.
also if you haven't already done so, I'd highly recommend adding an alert in papertrail so that you get an email whenever the text Exception shows up.
Thats a great idea to alert for exception! I see that my Papertrail only keeps 7 days. There is some kind of S3 archive feature. Will explore that.
How long are logs available in the basic Biff setup?
is this the way to access? clj -M:dev logs
yes, that's the command. you can also pass a number like clj -M:dev logs 3000 ; by default you get the most recent 300 lines.
To see all the logs, you can ssh in as root and then do journalctl -u app -- that'll go back really far I think. and see journalctl --help for more options. (`clj -M:dev logs` just does journalctl -u app -f -n 300 over ssh)
Ok, will try those log commands now. How would I find the POST endpoint?
I think you are right that i must try to learn more from the logs. But here is my form code, with style stuff stripped out. If you have time I would appreciate you feedback to to see if anything smells off. But maybe is a decent reference for someone doing something similar.
(def fresh-field? nil?)
(def returned-field? string?)
(def empty-field? empty?)
(defn filled-field? [x]
(not (empty-field? x)))
(def empty-returned-field?
(every-pred
returned-field?
empty-field?))
(def filled-returned-field
(every-pred
filled-field?
returned-field?))
(defn contact-input
[{field-name :name
field-value :value
:keys [name required? error?]
:or {required? false
type "text"}
:as params}]
(let
[field-label-str
(-> field-name
(string/replace "-" " ")
(string/capitalize))
field-empty?
(empty-returned-field? field-value)]
[input
(->
{:placeholder
(str field-label-str (when required? "*"))
:class []}
(merge params)
(cond->>
required? (add-class "required")
error? (add-class "error")
field-empty? (add-class "empty")
))]))
(def form-data
[{:field-name :first-name}
{:field-name :last-name}
{:field-name :email}
{:field-name :telephone
:required? false}])
(defn comments-input
[:div
[textarea
{:cols "30"
:placeholder "What are your landscape goals?"
:maxlength "1500"
:name "comments"
:rows "7"}]])
;; ___________________________________ .
(defn send-email-api-call! [postmark-api-key email-params]
(http/post ""
{:headers {"X-Postmark-Server-Token" postmark-api-key}
:as :json
:content-type :json
:form-params email-params
:throw-exceptions false}))
(defn email-success? [{:keys [status] :as result}]
(< status 400))
(defn send-email-w-error-logging! [postmark-api-key email-params]
(let [result (send-email-api-call! postmark-api-key email-params)
success? (email-success? result)]
(when-not success?
(log/error (:body result)))
success?))
(defn send-email-from-gsol!
[{gsol-email-address :postmark/from
:keys [biff/secret form-params] :as ctx}
email-params]
(send-email-w-error-logging! (secret :postmark/api-key)
(merge
{:From gsol-email-address}
email-params)))
(defn send-contact-emails!
[{gsol-email-address :postmark/from
:keys [form-params] :as ctx}]
(let
[{email-address :email
client-name :name
client-comment :comments
:keys [email telephone address]}
(cske/transform-keys csk/->kebab-case-keyword
form-params)]
(println "ran (send-contact-emails!)")
(send-email-from-gsol! ctx
{:To gsol-email-address
:Subject "New inquiry from contact page"
:TextBody
(str
"You recieved an inquery from "
email-address
(when client-name
(str "\n" "Name: " client-name"\n"))
(when telephone
(str "\n" "Telephone: " telephone "\n"))
(when address
(str "\n" "Address: " address "\n"))
(when client-comment
(str "\n" "Goals:\n" client-comment "\n")))})
(send-email-from-gsol! ctx
{:To email-address
:Subject "Thanks for contacting Grounded Solutions"
:TextBody "We will contact you shortly to discuss your beautiful Florida Native landscape.🌻 \n \n352-219-5381"})))
;; ___________________________________ .
(defn valid-email-str? [s]
(and
(auth/email-valid? {} s)
(some? s)
(string? s)
(string/includes? s "@")
(not= "" s)
(<= (count s) 100)))
(defn contact-sent []
[:p "Your form has been successfully submitted."])
(defn contact-error-message [h]
[:div
[:p "Sorry, there appears to be a problem with the form you submitted."]
[:p.form-correction h]])
(defn recaptcha-callback [fn-name form-id]
[::hiccup/unsafe-html
(str
"<script>"
"function " fn-name "(token) { "
"document.getElementById('" form-id "').requestSubmit();"
"}"
"</script>")])
(defstyled error-text :div
:text-sm :text-green-600
([error]
[:<>
(case error
"empty form"
"Please enter your contact information."
"invalid email"
"Email address is invalid. Please update."
"missing required fields"
"Please enter the required* fields."
"recaptcha"
"You failed the recaptcha test. Please try again, and make sure you aren't blocking scripts from Google."
default-form-message
)]))
(defn contact-form
[{:keys [recaptcha/site-key form-params params ::render-recaptcha] :as ctx}]
(let [error (:error params)
{email-address :email
client-name :name
client-comment :comment
:keys [email telephone address]
:as form-params}
(cske/transform-keys csk/->kebab-case-keyword
form-params)]
[:div#contact
[schedule-title
"Schedule a Consultation"]
(when error
[error-text error])
(biff/form
{:hx-post "/send-contact"
:hx-swap "outerHTML"
:hx-target "#contact"
:id "contact-form"
:hidden {:on-error "/"}
:_ (when render-recaptcha
(str "init call grecaptcha.render('g-recaptcha-id', {sitekey:'" site-key "'})"))
;; :hx-disabled-elt "this"
}
(recaptcha-callback "submitContact" "contact-form")
[:div.inputs
[contact-input
{:name "email"
;; :type "email"
:value email
:autocomplete "email"
:required? true
:error? (= error "invalid email")
:placeholder "Enter your email address"}]
[contact-input
{:name "name"
:required? true
:value client-name}]
[contact-input
{:name "telephone"
:type "tel"
:required? true
:value telephone}]
[contact-input
{:name "address"
:type "text"
:value address
:required? true}]
[comments-input]]
[email-submit-btn
(merge
(when site-key
{:data-sitekey site-key
:data-callback "submitContact"})
{:type "submit"
:class '[g-recaptcha]
:id "g-recaptcha-id"})
"Send"]
[recaptcha-disclosure])]))
(defn passed-recaptcha? [{:keys [biff/secret biff.recaptcha/threshold params]
:or {threshold 0.5}}]
(let [{:keys [success score]}
(:body
(http/post ""
{:form-params {:secret (secret :recaptcha/secret-key)
:response (:g-recaptcha-response params)}
:as :json}))]
(and success (or (nil? score) (<= threshold score)))))
(defn handle-form-submission
[{:keys [form-params params] :as ctx}]
(let [captcha-passed? (passed-recaptcha? ctx)
{email-address :email
client-name :name
client-comment :comment
:keys [email telephone address]
:as form-params}
(cske/transform-keys csk/->kebab-case-keyword
form-params)
all-fields (vec (vals form-params))
required-fields
[client-name
email-address
telephone
address]
error
(cond
(every? fresh-field? all-fields)
"empty form"
(not (valid-email-str? email-address))
"invalid email"
(not
(every? filled-returned-field required-fields))
"missing required fields") ]
(and (not (some? error)) captcha-passed?
(send-contact-emails! ctx))
(if error
[contact-form
(-> ctx
(assoc-in [:params :error] error)
(assoc ::render-recaptcha true))]
[contact-sent])))
;; example response header, instead of returning html
(comment
{:status 303
:headers {"location" (str "/contact?success=" "success")}})
(defn page [{:keys [path-params] :as ctx}]
(ui/page
(assoc ctx ::ui/recaptcha true)
[container
(contact-form ctx)])) > How would I find the POST endpoint?
It's the :action / :hx-post value you put in the form--`/send-contact` in this case. you could search for /send-contact in the logs and see if anything interesting comes before/after it (like an exception).
Thanks, looking for that now. Haven’t found any exceptions yet.
Is this error meaningful?
error: kex_exchange_identification: read: Connection reset by peer
nah, I'd ignore that, probably just more bot stuff
some bot trying to log in via ssh or something
Here’s an example of send-contact
Some warnings but no exception.
I just looked over your code. mostly looks fine, but did notice one thing: if passed-recaptcha? returns false, the user doesn't get an error message or anything. Maybe that's what's happening. I would update the error (cond ...) bit so it includes an error for recaptcha failing, and then show an error to the user when that happens. In handle-form-submission I'd also add log statement like "handle-form-submission {:email "
ok, those logs are interesting-- /send-contact is returning a 403 error. Where's that 403 status coming from? do you have some middleware that's checking if the user is signed in or something? assuming this is a public contact form, you probably should never be returning 403 for that endpoint.
Hmm im just trying do do the most basic thing, following the tutorial code (with some dom sugar)
I had to step away from my computer. I will review the captcha, and get a better sample of error to follow up. I definitely feel more confident to diagnose/resolve this now. Thank you so much for taking the time to review, and for your quick feedback… and all the Biff stuff!
oh actually maybe that 403 is coming from the csrf middleware. would make sense for that to return a 403 if a bot is trying to submit that form.
any time! hope you get to the bottom of it.
Ok that’s simple. Thanks!
logic looks good to me. to test you can do (let [captcha-passed? false ;(passed-recaptcha? ctx)
the user doesn’t get an error message or anything. Maybe that’s what’s happening. I would update theI updated this file to explicity register a captcha failure. https://github.com/chromalchemy/groundedsol/blob/master/src/gs/pages/contact.clj#L626 And may have fixed a bug in the conditional logic. Does this look ok to you now in terms of captcha/error logic? ps. I’m not sure how to test this. If i turn off javascript, on form submit, the page reloads with default error route, not the error logic on the page.error (cond ...)bit so it includes an error for recaptcha failing, and then show an error to the user when that happens. Inhandle-form-submission