Next.js ile Nodemailer Kullanarak E-posta Gönderme

Bu makalemde, Next.js'in App Router yapısını kullanarak Nodemailer ile e-posta gönderme işlevselliğini nasıl entegre edeceğinizi anlatıyor olacağım. Bir iletişim formu oluşturacak, Tailwind CSS ile stil verecek ve güvenli bir şekilde e-posta göndermek için bir API rotası oluşturacağım.

Ön Koşullar

Başlamadan önce aşağıdaki maddelere sahip olmanız gerekir:

  • JavaScript ve React/Next.js temel bilgisi
  • Node.js (18.x veya üstü) yüklü bir geliştirme ortamı
  • Bir Gmail hesabı veya başka bir SMTP sağlayıcısı (ör. SendGrid, Mailtrap)
  • Temel Tailwind CSS bilgisi (isteğe bağlı, ancak stil için kullanılacak)

1. Proje Kurulumu

Yeni bir Next.js projesi oluşturarak başlayalım. Terminalde aşağıdaki komutu çalıştırın:


    npx create-next-app@latest next-email-app

Sorulara şu şekilde yanıt verin:

  • TypeScript kullanmak ister misiniz? Hayır (veya Evet, isteğe bağlı)
  • ESLint kullanmak ister misiniz? Evet
  • Tailwind CSS kullanmak ister misiniz? Evet
  • src/ dizinini kullanmak ister misiniz? Evet
  • App Router kullanmak ister misiniz? Evet (önerilir)
  • İçe aktarma takma adını özelleştirmek ister misiniz? Hayır

Proje oluşturulduktan sonra dizine gidin ve sunucuyu başlatın:


    cd next-email-app
    npm run dev

Artık projenize http://localhost:3000 adresinden erişebilirsiniz.

2. Nodemailer Kurulumu

E-posta göndermek için Nodemailer'ı projemize eklememiz gerekiyor. Terminalde aşağıdaki komutu çalıştırın:


    npm install nodemailer

3. Çevresel Değişkenlerin Ayarlanması

Güvenli bir şekilde SMTP kimlik bilgilerini saklamak için çevresel değişkenler kullanacağız. Proje kök dizininde bir .env.local dosyası oluşturun ve aşağıdaki değişkenleri ekleyin:


    NODEMAILER_HOST=smtp.gmail.com
    NODEMAILER_PORT=465
    NODEMAILER_USER=your-email@gmail.com
    NODEMAILER_PASS=your-app-password

Notlar:

  • Gmail kullanıyorsanız, 2 Adımlı Doğrulama'yı etkinleştirmeli ve Google Hesap ayarlarından bir "Uygulama Şifresi" oluşturmalısınız. Bu şifreyi SMTP_PASS olarak kullanın. (Daha detaylı bilgi almak isterseniz google amcaya sorabilirsiniz.)

  • .env.local dosyasının .gitignore dosyasında olduğundan emin olun, böylece hassas bilgiler Git'e yüklenmez.

4. İletişim Formu Oluşturma

src/app/contact/page.js dosyası oluşturun ve Tailwind CSS ile stilize edilmiş bir iletişim formu ekleyin. Aşağıdaki kod, kullanıcıdan isim, e-posta ve mesaj alan bir form içerir:


    'use client';

    import { useState } from 'react';

    export default function ContactPage() {
      const [formData, setFormData] = useState({
        name: '',
        email: '',
        message: '',
      });
      const [status, setStatus] = useState(null);

      const handleChange = (e) => {
        setFormData({ ...formData, [e.target.name]: e.target.value });
      };

      const handleSubmit = async (e) => {
        e.preventDefault();
        setStatus('loading');

        try {
          const response = await fetch('/api/contact', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(formData),
          });

          const result = await response.json();
          if (response.ok) {
            setStatus('success');
            setFormData({ name: '', email: '', message: '' });
          } else {
            setStatus('error');
          }
        } catch (error) {
          setStatus('error');
        }
      };

      return (
        <div className="min-h-screen flex items-center justify-center bg-gray-100">
          <div className="bg-white p-8 rounded-lg shadow-lg w-full max-w-md">
            <h1 className="text-2xl font-bold mb-6 text-center">İletişim Formu</h1>
            <form onSubmit={handleSubmit} className="space-y-4">
              <div>
                <label htmlFor="name" className="block text-sm font-medium text-gray-700">
                  İsim
                </label>
                <input
                  type="text"
                  id="name"
                  name="name"
                  value={formData.name}
                  onChange={handleChange}
                  required
                  className="mt-1 p-2 w-full border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                />
              </div>
              <div>
                <label htmlFor="email" className="block text-sm font-medium text-gray-700">
                  E-posta
                </label>
                <input
                  type="email"
                  id="email"
                  name="email"
                  value={formData.email}
                  onChange={handleChange}
                  required
                  className="mt-1 p-2 w-full border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                />
              </div>
              <div>
                <label htmlFor="message" className="block text-sm font-medium text-gray-700">
                  Mesaj
                </label>
                <textarea
                  id="message"
                  name="message"
                  value={formData.message}
                  onChange={handleChange}
                  required
                  rows="4"
                  className="mt-1 p-2 w-full border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
                ></textarea>
              </div>
              <button
                type="submit"
                disabled={status === 'loading'}
                className="w-full bg-blue-500 text-white p-2 rounded-md hover:bg-blue-600 disabled:bg-blue-300"
              >
                {status === 'loading' ? 'Gönderiliyor...' : 'Gönder'}
              </button>
              {status === 'success' && (
                <p className="text-green-500 text-center">E-posta başarıyla gönderildi!</p>
              )}
              {status === 'error' && (
                <p className="text-red-500 text-center">E-posta gönderilirken bir hata oluştu.</p>
              )}
            </form>
          </div>
        </div>
      );
    }

Bu kod:

  • Kullanıcı dostu bir form oluşturur.
  • Form verilerini yönetmek için React'in useState kancasını kullanır.
  • Form gönderildiğinde /api/contact rotasına bir POST isteği yapar.
  • Gönderim durumu (yükleniyor, başarı, hata) için geri bildirim sağlar.

5. API Rotası Oluşturma

E-posta gönderme mantığını işlemek için bir API rotası oluşturacağız. src/app/api/contact/route.js dosyasını oluşturun ve aşağıdaki kodu ekleyin:


    import { NextResponse } from 'next/server';
    import nodemailer from 'nodemailer';

    export async function POST(request) {
      try {
        const { name, email, message } = await request.json();

        // Gerekli alanların kontrolü
        if (!name || !email || !message) {
          return NextResponse.json({ message: 'Tüm alanlar zorunludur' }, { status: 400 });
        }

        // Nodemailer transporter oluşturma
        const transporter = nodemailer.createTransport({
          host: process.env.NODEMAILER_HOST,
          port: process.env.NODEMAILER_PORT,
          secure: true,
          auth: {
            user: process.env.NODEMAILER_USER,
            pass: process.env.NODEMAILER_PASS,
          },
        });

        // E-posta içeriği
        const mailOptions = {
          from: `"İletişim Formu" <${process.env.NODEMAILER_USER}>`,
          to: "example@email.com",
          replyTo: email,
          subject: `Yeni Mesaj: ${name}`,
          text: `İsim: ${name}\nE-posta: ${email}\nMesaj: ${message}`,
          html: `
            <h2>Yeni İletişim Formu Mesajı</h2>
            <p><strong>İsim:</strong> ${name}</p>
            <p><strong>E-posta:</strong> ${email}</p>
            <p><strong>Mesaj:</strong> ${message}</p>
          `,
        };

        // E-posta gönderme
        await transporter.sendMail(mailOptions);

        return NextResponse.json({ message: 'E-posta başarıyla gönderildi' }, { status: 200 });
      } catch (error) {
        console.error('E-posta gönderim hatası:', error);
        return NextResponse.json({ message: 'E-posta gönderilirken hata oluştu' }, { status: 500 });
      }
    }

Not: Eğer mail gönderirken sorun yaşıyorsanız şu satırı src/app/api/contact/route.js dosyası içinde "transporter.auth" tan sonra ekleyin:


    tls: { rejectUnauthorized: false }
    

src/app/api/contact/route.js dosyasındaki kod:

  • İstekten JSON verilerini ayrıştırır ve gerekli alanları doğrular.
  • Nodemailer ile bir SMTP transporter oluşturur.
  • E-posta içeriğini hem metin hem de HTML formatında hazırlar.
  • E-postayı gönderir ve başarılı veya hata durumuna göre yanıt döndürür.

6. Güvenlik ve En İyi Uygulamalar

  • Çevresel Değişkenler: Hassas bilgileri (ör. SMTP kimlik bilgileri) asla kod içinde sabit olarak yazmayın. Her zaman .env.local veya platformunuzun çevresel değişkenlerini kullanın.

  • Hata Yönetimi: Yukarıdaki kod, eksik alanlar ve gönderim hataları için temel hata yönetimi içerir. Daha karmaşık projelerde, kullanıcıya daha ayrıntılı hata mesajları sağlamak için ek doğrulama eklenebilir.

  • Spam Koruması: Botları önlemek için reCAPTCHA veya benzeri bir doğrulama sistemi entegre etmeyi düşünün.

  • Üretim Ortamı: Gmail yerine SendGrid, Mailtrap veya AWS SES gibi profesyonel bir SMTP hizmeti kullanın, çünkü Gmail kişisel projeler için uygundur ancak üretimde spam klasörüne düşme riski vardır.

7. Test Etme

  1. Geliştirme sunucusunu çalıştırın: npm run dev
  2. Tarayıcıda http://localhost:3000/contact adresine gidin.
  3. Formu doldurun ve gönderin.
  4. Konsolda ve alıcı e-posta adresinde e-postanın geldiğini doğrulayın.

Eğer e-posta spam klasörüne düşüyorsa:

  • Gönderici adresinizin alan adını doğrulayın (ör. Gmail için SPF/DKIM ayarları).
  • Üretimde SendGrid gibi bir hizmet kullanmayı düşünün.

8. Ek Özellikler

  • Ekler: Kullanıcıların dosya yüklemesine izin vermek için formu multipart/form-data ile güncelleyin ve API rotasında dosya işleme mantığı ekleyin.

  • HTML Şablonları: E-postalar için daha karmaşık HTML şablonları oluşturmak için handlebars veya ejs gibi bir şablon motoru kullanın.

  • Bildirimler: react-toastify gibi bir kütüphane ile daha şık kullanıcı bildirimleri ekleyin.

Sonuç

Next.js App Router ile Nodemailer kullanarak bir iletişim formu üzerinden e-posta gönderme işlevselliğini nasıl entegre edebileceğinizi göstermeye çalıştım. Tailwind CSS ile kullanıcı dostu bir form tasarladım ve güvenli bir API rotası oluşturdum. Bu temel üzerine, projenize özel ihtiyaçlara göre ek özellikler ekleyebilirsiniz. Sorularınız varsa veya daha fazla yardım gerekiyorsa, bana ulaşabilirsiniz.


05 Ara 2025
Yorum