Can't replace email verification template
# support-questions-legacy
b
Can't replace email verification template
r
hey @bladerpc have you seen the email delivery section in our docs?
b
I believe I have, I used it for forgot password
But it doesn't work for email verification
I have this override:
Copy code
go
    if input.EmailVerification != nil {
                        verifyEmailLink := strings.Replace(input.EmailVerification.EmailVerifyLink, "/login", "", 1)
                        verifyEmailLink = strings.Replace(verifyEmailLink, "verify-email", "verify-email-confirm", 1)
                        var emailBody string
                        emailTemplate, err := email.GetEmailTemplate(email.VerifyEmailPath, map[string]string{
                            "VerifyEmailLink": verifyEmailLink,
                            "CurrentYear":     fmt.Sprintf("%d", time.Now().Year()),
                        })
                        if err != nil {
                            logger.Sugar().Error("Failed to retrieve verify email template template", "err", err)
                            emailBody = verifyEmailLink
                        } else {
                            emailBody = emailTemplate
                        }
                        user := input.EmailVerification.User
                        return emaildelivery.EmailContent{
                            Subject: "....",
                            Body:    emailBody,
                            IsHtml:  true,
                            ToEmail: user.Email,
                        }, nil

                    } 
} else if input.PasswordReset != nil {
.....

}
r
the customisations for email verification goes in the emailverification.init recipe
not in emailpasword.init
b
I reuse the struct for thirdpartyemailpassword.init
emailDelivery := &emaildelivery.TypeInput{...}
Do I need to make a unique one for both tpep and email verification? tpep uses it for forgot password, ev uses it for reset password template
r
you mean ev uses it for email verification template right?
b
yes
r
reusing it should be possible
can you log something in the function to make sure that it comes there?
b
i updated the above code to show you how i'm doing it rn
i just check which one is not nil
Sure, one sec.
Nope, never goes there.
r
can i see email verification init and tpep init (only the parts of emaildelivery config)
b
emailverification.Init(evmodels.TypeInput{ Mode: evmodels.ModeRequired, EmailDelivery: emailDelivery, }),
thirdpartyemailpassword.Init(&tpepmodels.TypeInput{ Override: &tpepmodels.OverrideStruct{ Functions: func(originalImplementation tpepmodels.RecipeInterface) tpepmodels.RecipeInterface { //First we copy the original impl originalSignUp := *originalImplementation.EmailPasswordSignUp // Then we override the functions we want to *originalImplementation.EmailPasswordSignUp = func(email string, password string, userContext supertokens.UserContext) (tpepmodels.SignUpResponse, error) { // just some captcha logic here }, EmailDelivery: emailDelivery, SignUpFeature: &epmodels.TypeInputSignUp{FormFields: []epmodels.TypeInputFormField{{ID: signUpRequestFormId}}}, Providers: []tpmodels.TypeProvider{ thirdparty.Github(tpmodels.GithubConfig{ ClientID: c.GetGithubOauthCredentials().Id, ClientSecret: c.GetGithubOauthCredentials().Secret, }), thirdparty.Google(tpmodels.GoogleConfig{ ClientID: c.GetGoogleOauthCredentials().Id, ClientSecret: c.GetGoogleOauthCredentials().Secret, }), }, }),
r
can i see the full definition of
emailDelivery
?
b
yes
Copy code
go
    emailDelivery := &emaildelivery.TypeInput{
        Service: emailpassword.MakeSMTPService(emaildelivery.SMTPServiceConfig{
            Settings: emaildelivery.SMTPSettings{
                From: emaildelivery.SMTPFrom{
                    Name:  "no-reply",
                    Email: "noreply@nodies.app",
                },
                Host:     smtpConfig.Host,
                Port:     smtpConfig.Port,
                Username: &smtpUsername,
                Password: smtpConfig.Password,
                Secure:   true,
            },
            Override: func(originalImplementation emaildelivery.SMTPInterface) emaildelivery.SMTPInterface {
                originalGetContent := *originalImplementation.GetContent

                *originalImplementation.GetContent = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) {

                    if input.EmailVerification != nil {
                        verifyEmailLink := strings.Replace(input.EmailVerification.EmailVerifyLink, "/login", "", 1)
                        verifyEmailLink = strings.Replace(verifyEmailLink, "verify-email", "verify-email-confirm", 1)
                        var emailBody string
                        emailTemplate, err := email.GetEmailTemplate(email.VerifyEmailPath, map[string]string{
                            "VerifyEmailLink": verifyEmailLink,
                            "CurrentYear":     fmt.Sprintf("%d", time.Now().Year()),
                        })
                        if err != nil {
                            logger.Sugar().Error("Failed to retrieve verify email template template", "err", err)
                            emailBody = verifyEmailLink
                        } else {
                            emailBody = emailTemplate
                        }
                        user := input.EmailVerification.User
                        return emaildelivery.EmailContent{
                            Subject: "Nodies DLB - Verify your email",
                            Body:    emailBody,
                            IsHtml:  true,
                            ToEmail: user.Email,
                        }, nil

                    } else if input.PasswordReset != nil {

                        passwordResetLink := strings.Replace(input.PasswordReset.PasswordResetLink, "/login", "", 1)
                        var emailBody string
                        emailTemplate, err := email.GetEmailTemplate(email.ForgotPasswordPath, map[string]string{
                            "PasswordResetLink": passwordResetLink,
                            "CurrentYear":       fmt.Sprintf("%d", time.Now().Year()),
                        })
                        if err != nil {
                            logger.Sugar().Error("Failed to retrieve password template", "err", err)
                            emailBody = passwordResetLink
                        } else {
                            emailBody = emailTemplate
                        }
                        user := input.PasswordReset.User
                        return emaildelivery.EmailContent{
                            Subject: "Nodies DLB - Password reset request",
                            Body:    emailBody,
                            IsHtml:  true,
                            ToEmail: user.Email,
                        }, nil
                    }
                    originalContent, err := originalGetContent(input, userContext)
                    return originalContent, err
                }

                return originalImplementation
            },
        }),
    }
r
ok so GetContent gets called for password reset, but not for email verification?
b
it seems like it
r
let me check amd get back.
@nkshah2 can help here.
b
Yep, printed an error inside PasswordReset, and it worked:
Copy code
go
2023-06-23T03:47:56.154-0500    ERROR   supertokens_auth        auth/supertokens.go:93                                                                                                                                                              i
in password reset
doesn't happen for email verification
n
Give me a second, ill go through all of the code you sent
b
yep, no problem thank you!
n
Just to confirm, the error occurs when you call the email verification token API?
b
yep, let me get the exact url
{{API_HOST}}/api/v1/auth/user/email/verify/token
n
In your custom
*originalImplementation.GetContent
, can you print the contents of input for when you trigger the email verification flow?
b
input type?
n
Copy code
*originalImplementation.GetContent = func(input emaildelivery.EmailType, userContext supertokens.UserContext) (emaildelivery.EmailContent, error) {
The value of
input emaildelivery.EmailType
b
It's never being entered.
Copy code
sh
com.supertokens {t: "2023-06-23T04:03:44-05:00", message: "getSession: Success!", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/recipe/session/recipeImplementation.go:251" sdkVer: "0.12.7"}

com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "Sending email verification email to {{email}}", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/recipe/emailverification/api/
implementation.go:133" sdkVer: "0.12.7"}

com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "errorHandler: Started", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/supertokens/supertokens.go:242" sdkVer: "0.12.7"}

com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "errorHandler: Checking recipe for match: thirdpartyemailpassword", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/supertokens/supertokens.go:
256" sdkVer: "0.12.7"}

com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "errorHandler: Matched with recipeId: thirdpartyemailpassword", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/supertokens/supertokens.go:258"
 sdkVer: "0.12.7"}

com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "errorHandler: Checking recipe for match: emailverification", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/supertokens/supertokens.go:256" s
dkVer: "0.12.7"}

com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "errorHandler: Matched with recipeId: emailverification", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/supertokens/supertokens.go:258" sdkVe
r: "0.12.7"}

com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "errorHandler: Checking recipe for match: session", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/supertokens/supertokens.go:256" sdkVer: "0.
12.7"}

com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "errorHandler: Matched with recipeId: session", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/supertokens/supertokens.go:258" sdkVer: "0.12.7
"}

2023-06-23T04:03:45.048-0500    INFO    zap@v0.1.0/zap.go:90    /api/v1/auth/user/email/verify/token
n
Have you intentionally removed the email from this log?
Copy code
com.supertokens {t: "2023-06-23T04:03:45-05:00", message: "Sending email verification email to {{email}}", file: "C:/Users/iuhas/go/packages/pkg/mod/github.com/supertokens/supertokens-golang@v0.12.7/recipe/emailverification/api/
implementation.go:133" sdkVer: "0.12.7"}
?
b
yes
redacted, it had my email in it
n
Right just making sure
Right so youre using
emailpassword.MakeSMTPService
for email verification as well. For email verification you need to use
emailverification.MakeSMTPService
instead
b
Ah I see that.
hmm
Maybe there should be a emailDelivery.MakeSMTPService
So it sounds like I'll need two different email delivery structs
n
Yeah theres no common one at the moment so it can be easy to miss. Well see if we can work on unifying them
b
no worries, this is ez fix on my side, thank you
n
Happy to help
b
will give it a shot now
actually if i'm using tpep, should it be tpep
n
Itll be tpep for the thirdpartyemailpassword init yeah, but for that one email password works too
Good practice would be to use tpep though
b
makes sense 😛
Copy code
go
    emailDeliveryForTpEp := &emaildelivery.TypeInput{
        Service: thirdpartyemailpassword.MakeSMTPService(smtpServiceConfig),
    }
    emailDeliveryForEmailVerification := &emaildelivery.TypeInput{
        Service: emailverification.MakeSMTPService(smtpServiceConfig),
    }
n
Yeah looks right
b
Copy code
{
  "status": "OK"
}
works!
n
Awesome!
2 Views