smtp initial setup, need to complete form to send order data
This commit is contained in:
parent
5a2af4ef1c
commit
03cae74a0e
@ -35,6 +35,32 @@ def upload():
|
|||||||
|
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
||||||
|
@app.route("/mail", methods=["POST"])
|
||||||
|
def mail():
|
||||||
|
email = request.json["email"]
|
||||||
|
password = request.json["password"]
|
||||||
|
order = request.json["order"]
|
||||||
|
|
||||||
|
|
||||||
|
if email is None:
|
||||||
|
return jsonify({"error": "Unauthorized"}), 401
|
||||||
|
|
||||||
|
if not bcrypt.check_password_hash(user.password, password):
|
||||||
|
return jsonify({"error": "Unauthorized"}), 401
|
||||||
|
|
||||||
|
# Cache session with redis
|
||||||
|
session["user_id"] = user.id
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"id": user.id,
|
||||||
|
"email": user.email
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.route("/orders", methods=["GET"])
|
||||||
|
def orders():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Handle Images
|
# Handle Images
|
||||||
@app.route('/serve-image/<filename>', methods=['GET'])
|
@app.route('/serve-image/<filename>', methods=['GET'])
|
||||||
def serve_image(filename):
|
def serve_image(filename):
|
||||||
|
|||||||
@ -25,6 +25,23 @@ class User(db.Model):
|
|||||||
email = db.Column(db.String(345), unique=True)
|
email = db.Column(db.String(345), unique=True)
|
||||||
password = db.Column(db.Text, nullable=False)
|
password = db.Column(db.Text, nullable=False)
|
||||||
|
|
||||||
|
class Orders(db.Model):
|
||||||
|
__tablename__ ="orders"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(80), unique=False, nullable=False)
|
||||||
|
email = db.Column(db.String(120), unique=False, nullable=False)
|
||||||
|
order = db.Column(db.String(345), unique=False, nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
return {
|
||||||
|
"id": self.id,
|
||||||
|
"firstName":self.first_name,
|
||||||
|
"lastName":self.last_name,
|
||||||
|
"email": self.email,
|
||||||
|
}
|
||||||
|
|
||||||
# class Category(db.Model):
|
# class Category(db.Model):
|
||||||
# __tablename__ = "categories"
|
# __tablename__ = "categories"
|
||||||
# id = db.Column(db.String(32), primary_key=True, unique=True, default=get_uuid)
|
# id = db.Column(db.String(32), primary_key=True, unique=True, default=get_uuid)
|
||||||
|
|||||||
Binary file not shown.
@ -14,21 +14,23 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.427.0",
|
"lucide-react": "^0.427.0",
|
||||||
"next": "14.1.4",
|
"next": "14.1.4",
|
||||||
"react": "^18",
|
"nodemailer": "^6.9.14",
|
||||||
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"sharp": "^0.33.4",
|
"sharp": "^0.33.4",
|
||||||
"tailwind-merge": "^2.5.0",
|
"tailwind-merge": "^2.5.2",
|
||||||
"tailwindcss-animate": "^1.0.7"
|
"tailwindcss-animate": "^1.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5",
|
"@types/node": "^20.14.15",
|
||||||
"@types/node": "^20",
|
"@types/nodemailer": "^6.4.15",
|
||||||
"@types/react": "^18",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18.3.0",
|
||||||
"autoprefixer": "^10.0.1",
|
"autoprefixer": "^10.4.20",
|
||||||
"postcss": "^8",
|
"eslint": "^8.57.0",
|
||||||
"tailwindcss": "^3.3.0",
|
"eslint-config-next": "14.1.4",
|
||||||
"eslint": "^8",
|
"postcss": "^8.4.41",
|
||||||
"eslint-config-next": "14.1.4"
|
"tailwindcss": "^3.4.10",
|
||||||
|
"typescript": "^5.5.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
frontend/src/app/api/emails/route.ts
Normal file
26
frontend/src/app/api/emails/route.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
export async function POST() {
|
||||||
|
const sender = {
|
||||||
|
name: 'My App',
|
||||||
|
address: 'no-reply@kevosattire.com',
|
||||||
|
}
|
||||||
|
|
||||||
|
const recipients = [{
|
||||||
|
name: 'John Doe',
|
||||||
|
address: 'fernando.delgado@kevosattire.com',
|
||||||
|
}]
|
||||||
|
|
||||||
|
try{
|
||||||
|
const result = await sendEmail({
|
||||||
|
sender,
|
||||||
|
recipients,
|
||||||
|
subject: "Thank you for placing an order with us!",
|
||||||
|
message: "We will follow up with a Paypal invoice soon!"
|
||||||
|
})
|
||||||
|
|
||||||
|
return Response.json({
|
||||||
|
accepted: result.accepted,
|
||||||
|
})
|
||||||
|
} catch (error){
|
||||||
|
return Response.json({message: 'Unable to send email at this time.'}, {status: 500})
|
||||||
|
}
|
||||||
|
}
|
||||||
33
frontend/src/components/Form/Form.tsx
Normal file
33
frontend/src/components/Form/Form.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"use client";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
const Form = () => {
|
||||||
|
const [result, setResult] = React.useState<Record<string, string>>({});
|
||||||
|
const [loading, setLoading] = React.useState<boolean>(false);
|
||||||
|
|
||||||
|
const sendEmail = () => {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
fetch('/api/emails', {
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => setResult(data))
|
||||||
|
.catch(error => setResult(error))
|
||||||
|
.finally(() => setLoading(false))
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-4">
|
||||||
|
<div className="my-4">{JSON.stringify(result)}</div>
|
||||||
|
|
||||||
|
{loading && <div className="my-4">Processing...</div>}
|
||||||
|
|
||||||
|
<button onClick={sendEmail} className="bg-blue-500 rounded p-3">
|
||||||
|
Send email
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Form;
|
||||||
30
frontend/src/lib/mail.utils.ts
Normal file
30
frontend/src/lib/mail.utils.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import nodemailer from "nodemailer";
|
||||||
|
import Mail from "nodemailer/lib/mailer";
|
||||||
|
import SMTPTransport from "nodemailer/lib/smtp-transport";
|
||||||
|
|
||||||
|
const transport = nodemailer.createTransport({
|
||||||
|
host: process.env.MAIL_HOST,
|
||||||
|
port: process.env.MAIL_PORT,
|
||||||
|
secure: process.env.NODE_ENV !== 'development', //true
|
||||||
|
auth: {
|
||||||
|
user: process.env.MAIL_USER,
|
||||||
|
pass: process.env.MAIL_PASSWORD
|
||||||
|
},
|
||||||
|
} as SMTPTransport.Options)
|
||||||
|
|
||||||
|
type SendEmailDto = {
|
||||||
|
sender: Mail.Address,
|
||||||
|
recipients: Mail.Address[],
|
||||||
|
subject: string;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
export const sendEmail = async (dto: SendEmailDto) => {
|
||||||
|
const { sender, recipients, subject, message} = dto;
|
||||||
|
|
||||||
|
return await transport.sendMail({
|
||||||
|
from: sender,
|
||||||
|
to: recipients,
|
||||||
|
html: message,
|
||||||
|
text: message,
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user