This Java-based application is for sending emails with an attachment to a large number of recipients at once. You can provide a list of emails as a CSV file, containing the receivers' names and email addresses. According to the details you provided an email will be sent to receivers. This program is containerized using Docker for ease of use in any environment.
This is how your output might look like if you are sending emails to request an internship. To customize this refer to the customization section.
Subject: Application for Software Engineering Internship at Google
Body:
Dear Sir/Madam,
I hope this message finds you well. My name is Sundar Pichai, and I am currently a third-year undergraduate studying
Computer Science at the University of Colombo School of Computing. I am writing to express my keen interest in securing a
Software Engineering internship position at Google.
...
I have attached my resume for your review and am available for an interview at your earliest convenience. Thank
you for considering my application. I look forward to the possibility of joining Google as a Software Engineering
intern and contributing to your team's success.
Best regards,
Buddhika Senanayake.
+94 71 234 5678
[email protected]
https://www.linkedin.com/in/buddhikanip/
Attachment: resume.pdf
.
├── Dockerfile
├── README.md
├── docker-compose.yml
├── pom.xml
└── src
├── main
│  ├── java
│  │  └── com
│  │  └── email
│  │  ├── EmailServer.java
│  │  ├── Mail.java
│  │  ├── Main.java
│  │  └── User.java
│  └── resources
│  ├── Emails.csv
│  ├── email_body.txt
│  └── resume.pdf
└── test
└── java
flowchart TD
A[Start Application] --> B[Load Environment Variables]
B -->|Success| C[Initialize Email Server]
B -->|Failure| Z[Terminate Process]
C --> D[Load Email CSV File]
D -->|Success| E[Iterate Over CSV Rows]
D -->|Failure| Z
E -->|Valid Row| F[Extract Recipient Emails]
E -->|Invalid Row| G[Log Invalid Row & Update Status]
F -->|Recipients Found| H[Draft Email]
F -->|No Recipients| I[Log Missing Recipients & Update Status]
H --> H1[Set Email Subject]
H1 --> H2[Generate Email Body]
H2 --> H3[Attach Resume]
H3 --> J[Send Email]
J -->|Success| K[Log Success & Update Status]
J -->|Failure| L[Log Failure & Update Status]
E -->|Already Processed Row| M{More Rows?}
M -->|Yes| E
M -->|No| N[Write Results Back to CSV]
N --> O[End Process]
- Java 17 (or higher)
- Docker and Docker Compose (Optional)
-
Clone the Repository
git clone https://github.com/Buddhikanip/Mass-Email-Sender.git cd Mass-Email-Sender
-
Set up your .env file
-
Copy the
.env.example
file to create your.env
file:cp .env.example .env
-
Your newly created
.env
file looks like this.# Email server settings EMAIL_USERNAME=[email protected] EMAIL_PASSWORD=your-email-app-password EMAIL_HOST=smtp.gmail.com EMAIL_PORT=587 # Email content EMAIL_SUBJECT=Application for Software Engineering Internship at {company} EMAIL_BODY=email_body.txt # Personal details for the cover letter NAME=Buddhika Senanayake PHONE=+94 71 234 5678 EMAIL=[email protected] LINKEDIN=https://www.linkedin.com/in/buddhikanip/ # Resume file RESUME=resume.pdf
EMAIL_USERNAME
: Your email address (send address)
EMAIL_PASSWORD
: If you are using Gmail this is a 16-digit passcode that allows a third-party app or device to access your Google Account. (Not your Gmail password) For referenceIf you are using some other email service your email server access password.
-
-
Update Emails.csv with your recipients details
-
Paste your own resume in
src/main/resources
directory and rename it asresume.pdf
-
Build and Run with Docker
- Build and Run Docker image:
docker-compose up --build
- Build and Run Docker image:
-
Run Without Docker
- Compile the project:
mvn clean install
- Execute the application:
java -jar target/<your-jar-file>.jar
- Compile the project:
-
Check Logs Monitor the logs to ensure emails are being sent:
docker logs <container-id>
-
Emails.csv: Contains the recipient details and sending status.
-
email_body.txt: A customizable template as text file containing email body.
Dear Sir/Madam, I hope this message finds you well. My name is {name}, and I am currently a third-year undergraduate studying Computer Science at the University of Colombo School of Computing. I am writing to express my keen interest in securing a Software Engineering internship position at {company}. ... I have attached my resume for your review and am available for an interview at your earliest convenience. Thank you for considering my application. I look forward to the possibility of joining {company} as a Software Engineering intern and contributing to your team's success. Best regards, {name}. {phone} {email} {linkedIn}
-
resume.pdf: Your resume file.
-
.env.example: Example .env file.
-
How to customize your recipient email list: Emails.csv
Status Company Recipient 1 Recipient 2 Recipient 3 Sent Google [email protected] [email protected] [email protected] Failed Netflix [email protected] [email protected] Pending Apple [email protected] - First column:
status
Initially you can keep it empty. The program will append the status of the email to that column.
- Second column:
company name
- Third column onwards
Receiving emails under the specified company. One cell can contain only one email. If there's a second or third email for the same company, you can put them in the 4th column onwards
Rows with the first column value as
sent
will be skipped without sending out the email. You can customize the logic in Main.java file (line 49-54).String status = row[0]; if ("Sent".equalsIgnoreCase(status)) { log.info("Skipping already processed row: {}", Arrays.toString(row)); updatedData.add(row); continue; }
- First column:
-
How to customize email subject
Email subject is fetched from
.env
file (line 8). You can customize it according to your requirements. The{company}
placeholder is replaced with the company name inEmails.csv
. If you don't want the company name you can remove that placeholder. (This will work but is not recommended)EMAIL_SUBJECT=Application for Software Engineering Internship at {company}
- Recommended way
- Remove
{company} placeholder like above
- Update Mail.java
draftEmail
function first line as belowString subject = user.emailSubject();
- Remove
- Recommended way
-
How to customize email body: email_body.txt
{comapny}
inemail_body.txt
fetched from the second column ofEmails.csv
.{name}
{phone}
{email}
{linkedIn}
values are fetched from your.env
file. In theemail_body.txt
place{company}
{name}
{phone}
{email}
{linkedIn}
wherever you need to use their values. Then the values will be assigned to them by the below code snippet. (Mail.javaline 45-49
)String body = bodyTemplate.replace("{name}", user.name()) .replace("{company}", company) .replace("{phone}", user.phone()) .replace("{email}", user.email()) .replace("{linkedIn}", user.linkedIn());
If you don't want
{name}
{phone}
{email}
{linkedIn}
as environment variables you can simply hardcode these values in youremail_body.txt
. Then you have to remove those variables form your.env
,Main.java
,User.java
andMail.java
files.- If you want to remove them follow these steps.
-
Remove below lines from .env. (
line 11-15
)# Personal details for the cover letter NAME=Buddhika Senanayake PHONE=+94 71 234 5678 EMAIL=[email protected] LINKEDIN=https://www.linkedin.com/in/buddhikanip/
-
Update Main.java
line 34
.User user = new User(emailSubject, emailBody, resume);
-
Remove below lines from Main.java. (
line 24-27
)private static final String name = getEnv("NAME"); private static final String phone = getEnv("PHONE"); private static final String email = getEnv("EMAIL"); private static final String linkedIn = getEnv("LINKEDIN");
-
Update Mail.java
line 45-49
as below.String body = bodyTemplate.replace("{company}", company);
-
Update User.java
line 3-5
as below.public record User(String emailSubject, String emailBody, String resume) {}
-
Likewise, you can add new values to your email body.
- If you want to remove them follow these steps.
-
Send Email without Attachments
-
Have to Update Mail.java file
draftEmail
function. Follow below steps.-
Remove this code section in
draftEmail
function.MimeBodyPart bodyPart = new MimeBodyPart(); bodyPart.setText(body, "utf-8"); MimeBodyPart attachmentPart = new MimeBodyPart(); String attachmentPath = String.format("src/main/resources/%s", user.resume()); // Local path File resumeFile = new File(attachmentPath); if (!resumeFile.exists()) { attachmentPath = String.format("/app/resources/%s", user.resume()); // Docker path } attachmentPart.attachFile(attachmentPath); MimeMultipart multipart = new MimeMultipart(); multipart.addBodyPart(bodyPart); multipart.addBodyPart(attachmentPart); mimeMessage.setContent(multipart);
-
Paste this code line in deleted section.
mimeMessage.setText(body, "utf-8");
-
Final
draftEmail
function must look like this.public void draftEmail(String recipient, String company, User user) throws MessagingException, IOException { String subject = user.emailSubject().replace("{company}", company); // Read the cover letter String templatePath = String.format("src/main/resources/%s", user.emailBody()); // Local path if (!new File(templatePath).exists()) { templatePath = String.format("/app/resources/%s", user.emailBody()); // Docker path } String bodyTemplate = Files.readString(Paths.get(templatePath)); // Replace placeholders with actual values String body = bodyTemplate.replace("{name}", user.name()) .replace("{company}", company) .replace("{phone}", user.phone()) .replace("{email}", user.email()) .replace("{linkedIn}", user.linkedIn()); mimeMessage = new MimeMessage(newSession); mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient)); mimeMessage.setSubject(subject); mimeMessage.setText(body, "utf-8"); }
-
-
Remove below line in
.env
file.# Resume file RESUME=resume.pdf
-
Update Main.java file as below.
-
Remove below code line.
private static final String resume = getEnv("RESUME");
-
Update below code line. (Remove
resume
in the constructor)User user = new User(name, phone, email, linkedIn, emailSubject, emailBody);
-
-
Update User.java file. (Remove
String resume
in the constructor)public record User(String name, String phone, String email, String linkedIn, String emailSubject, String emailBody) {}
-
-
Send multiple attachments
- Update Mail.java file
draftEmail
function file attachment section as below.These example file names are hardcoded in an array list. If you want to get them via
.env
you can add these file names as an array and fetch them inMain.java
and so on.List<String> attachments = Arrays.asList("resume.pdf","portfolio.pdf"); MimeMultipart multipart = new MimeMultipart(); multipart.addBodyPart(bodyPart); for (String attachment : attachments) { MimeBodyPart attachmentPart = new MimeBodyPart(); String attachmentPath = String.format("src/main/resources/%s", attachment); // Local path File file = new File(attachmentPath); if (!file.exists()) { attachmentPath = String.format("/app/resources/%s", attachment); // Docker path } attachmentPart.attachFile(attachmentPath); multipart.addBodyPart(attachmentPart); } mimeMessage.setContent(multipart);
- Update Mail.java file
- File Attachment: Automatically attach the specified file.
- Dockerized Deployment: Simplifies setup and ensures a consistent environment.
- Multiple Emails At Once: Sends specified emails to a large number of specified receivers at once.
- Customizable: Output can be customized according to your own will.
- CSV-based Management: Tracks sending status and recipient details.
This project is licensed under the MIT License - see the LICENSE file for details.
Feel free to submit issues or pull requests for improvements