def dispatchInvitation(invitation: Invitation) -> bool:
    """
    Sends an email to an invitee
    """
    try:
        assert not invitation.mailed and not invitation.fulfilled
    except AssertionError:
        logger.warning(f"Invitation for {invitation.email} was not sent: "
                       "Already fulfilled!")
        return False

    if invitation.refkey is None:
        invitation.refkey = referralKeygen(invitation.email)
        invitation.save()

    if invitation.customemail and invitation.customsig:
        et = EmailTemplate(
            subject=settings.DEFAULT_EMAIL_TITLE,
            headline="Conflict Cartographer",
            message=invitation.customemail,
            signature=invitation.customsig,
        )
    else:
        try:
            et = EmailTemplate.objects.get(active=True, email_type="inv")
        except EmailTemplate.DoesNotExist:
            et = EmailTemplate.objects.create(
                active=True,
                subject=settings.DEFAULT_EMAIL_TITLE,
                email_type="inv")

    html = renderEmailTemplate(et, {"link": invitation.invitationLink()})
    plaintext = re.sub("\[[^\)]+", invitation.invitationLink(), et.message)

    call = {
        "subject": et.subject,
        "message": plaintext,
        "html_message": html,
        "from_email": settings.EMAIL_FROM_ADDRESS,
        "recipient_list": [invitation.email]
    }

    try:
        mail.send_mail(**call)
    except ConnectionRefusedError:
        logger.error("Failed to send email to %s, connection refused!",
                     invitation.email)
        return False
    else:
        logger.info("Sent email to %s", invitation.email)
        invitation.mailed = True
        invitation.save()
        return True
    def test_dispatch_and_register(self):
        """
        Long-form test that tests creating and sending an invite, and then
        registering a user by following the referral link in the invitation email.
        """
        countries = [
            Country(gwno=i, name=str(i), shape={}, simpleshape={})
            for i in range(5)
        ]
        for c in countries:
            c.save()

        i = Invitation(email="*****@*****.**")
        i.save()
        i.countries.set(countries)
        dispatchInvitation(i)

        m = mail.outbox[0]

        # Mailed flag
        self.assertTrue(i.mailed)

        # Email has proper title
        self.assertEqual(m.subject, settings.DEFAULT_EMAIL_TITLE)

        # Email contains ref. key
        self.assertIsNotNone(re.search(i.refkey, m.body))

        r = self.client.get(i.invitationLink(), follow=True)
        location, *_ = r.redirect_chain[-1]

        soup = BeautifulSoup(r.content, features="html.parser")

        regform = soup.find("form")
        usernameInput = regform.find("input", attrs={"name": "username"})

        # Email is in the username form
        self.assertEqual(usernameInput["value"], i.email)

        url = regform.action if regform.action else location
        method = regform.method if regform.method else "POST"

        getattr(self.client,
                method.lower())(url, {
                    "username": usernameInput["value"],
                    "password1": hashlib.md5(b"1234").hexdigest(),
                    "password2": hashlib.md5(b"1234").hexdigest()
                })

        # User was created
        try:
            u = User.objects.get(email=i.email)
        except User.DoesNotExist:
            self.fail("User was not created")

        # Make sure all countries were added
        self.assertEqual({c.pk
                          for c in countries},
                         {c.pk
                          for c in u.profile.countries.all()})