diff --git a/cgi-bin/form.py b/cgi-bin/form.py index 9fd4268..2452cd6 100755 --- a/cgi-bin/form.py +++ b/cgi-bin/form.py @@ -158,7 +158,10 @@ def get_form_value( return (value_object.filename or "upload"), value_object.file.read() else: try: - return cast(form.getfirst(name)) + result = cast(form.getfirst(name)) + if isinstance(result, str): + result = result.strip() + return result except (TypeError, ValueError): fail("400 Bad Request", f"Invalid value for field: {name}") @@ -187,6 +190,7 @@ if not isinstance(hcaptcha_data, Mapping) or not hcaptcha_data.get("success", Fa # Extract all the actually provided form data. This is different from form to # form (see the match block below). contact_name = get_form_value("contactname") +contact_names = contact_name.split(" ") contact_email = get_form_value("contactemail") if not EMAIL_REGEX.fullmatch(contact_email): @@ -289,13 +293,41 @@ ZAMMAD_TOKEN = os.environ.get("ZAMMAD_TOKEN", "") session.headers.update(Authorization=f"Token token={ZAMMAD_TOKEN}") try: + # Create a new user for the client. For some reason, using "guess:{email}" as the + # customer_id when creating the ticket doesn't really work, as described in the + # Zammad documentation [1]. Instead, we sometimes need to explictily create the + # user beforehand. See this discussion [2] for more details. + # [1]: https://docs.zammad.org/en/latest/api/ticket/index.html#create + # [2]: https://codeberg.org/angestoepselt/homepage/issues/141 + response = session.post( + f"{ZAMMAD_URL}/api/v1/users", + json=dict( + # Yes, yes... This goes against pretty much all best practices for parsing + # names. But: it's only internal and we save the name verbatim again below + # so we're going to go ahead and do it anyway. + firstname=" ".join(contact_names[:-1]) if len(contact_names) >= 2 else "?", + lastname=contact_names[-1], + email=contact_email, + ) + ) + if response.status_code == 422: + # This email address is already in use by another user. + customer_id = f"guess:{contact_email}" + else: + response.raise_for_status() + customer_id = response.json()["id"] + assert isinstance(customer_id, (str, int)) + # Add the actual ticket to the system. response = session.post( f"{ZAMMAD_URL}/api/v1/tickets", + headers={ + "X-On-Behalf-Of": contact_email, + }, json=dict( title=f"Kontaktformular {contact_name} – {form_name}", group=form_group, - customer_id=f"guess:{contact_email}", + customer_id=customer_id, article=dict( type="web", internal=True,