Error creating new account :: unable to parse email address

1. The problem I’m having:

The issue is that the certificate is never issued for a domain.

The only similar issue I found was this one from Cory few years back:

Note: my system handles thousands of domains and this doesn’t seem to happen often. I only found 3-4 domains affected by this.

2. Error messages and/or full log output:

My logs are a bit different to Cory’s and mention that users is invalid email:

{"level":"info","ts":"2025-03-21T10:19:30.279Z","logger":"tls.obtain","msg":"obtaining certificate","identifier":"partners.portaone.com"}
{"level":"error","ts":"2025-03-21T10:19:30.949Z","logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"partners.portaone.com","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 400 urn:ietf:params:acme:error:invalidContact - Error creating new account :: unable to parse email address"}
{"level":"error","ts":"2025-03-21T10:19:30.949Z","logger":"tls.obtain","msg":"will retry","error":"[partners.portaone.com] Obtain: registering account [mailto:users] with server: attempt 1: https://acme-staging-v02.api.letsencrypt.org/acme/new-acct: HTTP 400 urn:ietf:params:acme:error:invalidContact - Error creating new account :: unable to parse email address","attempt":2,"retrying_in":120,"elapsed":61.233585642,"max_duration":2592000}

3. Caddy version:

2.8.4

4. How I installed and ran Caddy:

a. System environment:

Docker (Linux)

b. Command:

caddy run --config /etc/caddy/caddy.json

d. My complete Caddy config:

{
  "apps": {
    "http": {
      "servers": {
        "proxy_status_server": {
          "listen": [
            ":8082"
          ],
          "automatic_https": {
            "disable": true,
            "disable_redirects": true
          },
          "routes": [
            {
              "match": [
                {
                  "path": [
                    "/custom-domains-proxy-status"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "static_response",
                  "status_code": 200,
                  "body": "OK"
                }
              ],
              "terminal": true
            }
          ]
        },
        "tls_terminator": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "partners.portaone.com"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "upstreams": [
                    {
                      "dial": "domain.com:443"
                    }
                  ],
                  "transport": {
                    "protocol": "http",
                    "tls": {}
                  },
                  "headers": {
                    "request": {
                      "set": {
                        "Host": [
                          "{http.reverse_proxy.upstream.host}"
                        ]
                      }
                    }
                  }
                }
              ],
              "terminal": true
            }
          ],
          "logs": {}
        }
      }
    },
    "tls": {
      "automation": {
        "policies": [
          {
            "on_demand": true
          }
        ],
        "on_demand": {
          "ask": "https://[redacted_domain]/control/caddy/ask",
          "rate_limit": {
            "interval": "10m",
            "burst": 100
          }
        }
      },
      "cache": {
        "capacity": 100000
      }
    }
  },
  "admin": {
    "identity": {
      "issuers": [
        {
          "module": "acme",
          "email": "[redacted]"
        }
      ]
    }
  },
  "logging": {
    "logs": {
      "default": {
        "exclude": [
          "http.log.access"
        ],
        "writer": {
          "output": "file",
          "filename": "/var/log/caddy/caddy.log",
          "roll": true,
          "roll_size_mb": 64,
          "roll_keep": 20
        },
        "encoder": {
          "format": "json",
          "time_format": "iso8601"
        }
      },
      "log0": {
        "writer": {
          "output": "file",
          "filename": "/var/log/caddy/access.log",
          "roll": true,
          "roll_size_mb": 64,
          "roll_keep": 20
        },
        "encoder": {
          "format": "json",
          "time_format": "iso8601"
        },
        "include": [
          "http.log.access"
        ]
      }
    }
  },
  "storage": {
    "module": "s3",
    "host": "s3.amazonaws.com",
    "bucket": "[redacted_bucket_name]",
    "prefix": "[redacted]",
    "insecure": false
  }
}

I don’t understand where is that mailto:users coming from?

Thank you all for any help you can give me! :slight_smile:

I don’t see anything regarding users in the Caddy config, but I wonder if there is a script utilized somewhere in the chain that references a user or group of users, and that it is incorrectly parsed because of an invalid email from a user.

Do you know of anything set up like that?

Did you add this recently?

I don’t have any script like that. Also please note that I have many other domains and certs are issued without a problem.

No, it’s been there for years.

@francislavoie @matt - do you maybe have any idea where to even start debugging this?

I just deleted the acme directory from my storage. Wild guess but let’s see if it helps.

Deleting acme directory from my storage did not help.

To me this smells like a storage module bug.

Obtain: registering account [mailto:users] with server: attempt 1: https://acme-staging-v02.api.letsencrypt.org/acme/new-acct: HTTP 400 urn:ietf:params:acme:error:invalidContact - Error creating new account :: unable to parse email address

An email address of “users” is obviously wrong, but that’s the name of the folder that Caddy scans for email addresses when none are provided. It asks the storage module to list the keys (folders) within the “acme/<ca>/users” folder, which keys are email addresses previously used.

The storage module should be returning a list of keys WITHIN that folder, not the folder itself.

2 Likes

I have a strong suspicion this is somehow related to my S3 storage, I use GitHub - ss098/certmagic-s3: Certmagic S3-compatible driver written in Go | Caddy 证书存储 Certmagic 接口分布式对象存储实现.

Also remember that S3 is not a suitable storage backend because it does not provide atomic operations (I have seen some users couple it with a proper DB like redis or dynamodb, but then, why not just use the proper thread-safe DB as the entire storage driver?) – but that’s a separate issue, most likely.

3 Likes

Oh lol, I literally just wrote I have a strong suspicion it’s my S3 storage module.

As a quick fix, I’ll build my Caddy with older version of S3 storage module.

PS
This is the final straw I needed to move away from S3 as my storage. I know you’ve been saying this for a long time and it seems that most of my issues always come from using S3.

2 Likes

Just to confirm it was my s3 storage module. I built Caddy with latest storage module commit I knew worked and now it’s all fine.

3 Likes