#SSR email verification - not sending email to the user

11 messages · Page 1 of 1 (latest)

uncut haven
#

SSR email verification - not sending email to the user

fading pine
#

I continue to struggle to get an all SSR createVerification("http://somehost.com") going. I did get an client SDK based request going and was able to receive mails through my own SMTP provider. So it's definitely not mailing or spam folder issues.

I can narrow the problem down to not being able to get an authenticated session whenever I try to call account.createVerification from the server. Here's an API example. Note I am using astro 5.8 which allows context.session to persist sessions across API calls.

import { createAdminClient, createSessionClient } from "server/appwrite";
import { ID } from "node-appwrite";
import type { APIContext } from "astro";


const { admin_account } = createAdminClient();

// src/pages/api/signup.ts
export async function GET(context: APIContext) {
    try {
        const user_uid = ID.unique();
       
        const sessionData = await admin_account.createEmailPasswordSession(
            'myaddress@someprovider.com',
            'mattpass1234'
        );
     
        
        context.session?.set("appsession", JSON.stringify(sessionData));
        console.log(await context.session?.get("appsession"));
        const { account } = await createSessionClient(context);

        console.log(account.get());

        // works, sends an email 
       account.createEmailToken('6836f622000bc4cb5f37','myaddress@someprovider.com');

       // won't send an email 
       account.createVerification("http://localhost:4321");

       return new Response("done", {status: 200});
    } catch (error) {
        return new Response("Signup failed", { status: 400 });
    }
}

#

here's my createSessionClient function

export async function createSessionClient(context) {
  const client = new Client()
    .setEndpoint(import.meta.env.PUBLIC_APPWRITE_ENDPOINT)
    .setProject(import.meta.env.PUBLIC_APPWRITE_PROJECT);

  // Retrieve session secret from Astro's SSR session storage
  const sessionSecret = await context.session?.get("appsession");

  client.setSession(sessionSecret);

  return {
    get account() {
      return new Account(client);
    },
  };
}

I tried different variants, also without the context thing, simple passing on sessionData and trying to set the session. None of it worked when sending from a server. According to the docs, I feel like I don't even need to admin client session here (a session that uses and API key), but rather just set the apprite Project ID header somehow. Can you help getting it done without storing COOKIES on the client side?

stark tulip
fading pine
#

Thanks your reply @stark tulip . No, it's not appwrite cloud. It's self-hosted using docker-compose. All endpoints and the backend work well on my local Docker Desktop as well as on my small server. Thanks for the pointer, I was obviously a little sloppy here, adding await gives back a result which looks decent to me, but the account.createVerification still gets rejected. Here's part of the output:

21:39:53 [200] /api/signup 217ms
21:39:53 [ERROR] [UnhandledRejection] Astro detected an unhandled rejection. Here's the stack trace:
AppwriteException: User (role: guests) missing scope (account)
    at _Client.call (file:///.........../node_modules/node-appwrite/dist/client.mjs:284:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
  Hint:
    Make sure your promises all have an `await` or a `.catch()` handler.
  Error reference:
    https://docs.astro.build/en/reference/errors/unhandled-rejection/
  Stack trace:
    at /................/node_modules/node-appwrite/dist/client.mjs:284:13
    [...] See full stack trace in the browser, or rerun with --verbose.
stark tulip
stark tulip
fading pine
#

Thanks for your patience and guidance @Steven, just getting used to this community. Will tag accordingly next time.
What's strange to me is that:

<script>
    
import { Client, Account } from "appwrite";

const client = new Client()
    .setEndpoint(import.meta.env.PUBLIC_APPWRITE_ENDPOINT)
    .setProject(import.meta.env.PUBLIC_APPWRITE_PROJECT);

const account = new Account(client);


// Check if a session exists before creating a new one
account.get()
    .then(response => {
        console.log("User is already logged in:", response);
        const result = account.createVerification(
            'https://morebeachvolley.ch'
        );
        console.log(result);
    })
    .catch(async () => {
        console.log("No active session, logging in...");
        const session = await account.createEmailPasswordSession("mymail@example.com", "password");
        console.log("New session created:", session);
    });

    
</script>

works perfectly fine dishing out mails like it's never been different.

#

I guess this has to do with the fact, that account.createEmailPasswordSession keeps the auth active through browser headers/cookies something SSR can't do.
Still, looking at the source code of the appwrite SDK, I see that createVerification does not have any auth on its own nor any place it gets the email address and name from. Hence, I guess it gets that information from a preview auth, e.g., through account.createEmailPassword but I can't get it to go.

I might be stubborn, but I guess it would be nice if wasn't relying on client side JS to make sure my user can verify. As you can see I am new to this, any help very much appreciated - really eager to figure it out the SSR way. Do you think ditching the SDK and just using the REST API from Astro's REST calling capabilities would be a better option?

stark tulip
fading pine
#

I did follow this one right here: https://appwrite.io/docs/products/auth/server-side-rendering

At least I thought so, I feel like it's something very little, but so far not even a day off or the famous walk in the park helped. I am missing something or the maybe the docs are missing something are ambigous at some crucial point. I'll try plain REST now, without the SDK. This should give me more control and having to process the response myself, might help get a better understanding.

How to implement SSR authentication with Appwrite