Repository: r0hi7/Trashemail
Branch: master
Commit: c2783b857462
Files: 48
Total size: 81.7 KB
Directory structure:
gitextract_x8eo6s08/
├── .github/
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .gitmodules
├── LICENSE
├── Makefile
├── README.md
├── TrashEmailService/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── io/
│ │ └── github/
│ │ └── trashemail/
│ │ ├── Configurations/
│ │ │ ├── EmailServerConfig.java
│ │ │ └── TrashEmailConfig.java
│ │ ├── DTO/
│ │ │ ├── ConnectorStats.java
│ │ │ ├── CreateEmailRequest.java
│ │ │ ├── CreateEmailResponse.java
│ │ │ ├── DeleteEmailRequest.java
│ │ │ ├── DeleteEmailResponse.java
│ │ │ ├── Email.java
│ │ │ ├── SendEmailRequest.java
│ │ │ ├── TelegramConnectorStats.java
│ │ │ └── TrashEmailStats.java
│ │ ├── EmailServerInteraction.java
│ │ ├── Respositories/
│ │ │ ├── FreeUserIdRepository.java
│ │ │ └── UsedUserIdRepository.java
│ │ ├── TrashEmailApplication.java
│ │ ├── TrashEmailResource.java
│ │ ├── exceptions/
│ │ │ ├── EmailAliasNotCreatedExecption.java
│ │ │ ├── EmailAlreadyExsitExecption.java
│ │ │ └── EmailNotFoundExecption.java
│ │ ├── models/
│ │ │ ├── EmailAllocation.java
│ │ │ ├── EmailCounter.java
│ │ │ ├── FreeUserId.java
│ │ │ └── UsedUserId.java
│ │ └── repositories/
│ │ ├── EmailAllocationRepository.java
│ │ └── EmailCounterRepository.java
│ └── test/
│ └── java/
│ └── io/
│ └── github/
│ └── trashemail/
│ ├── DTO/
│ │ ├── ConnectorStatsTest.java
│ │ ├── CreateEmailRequestTest.java
│ │ ├── CreateEmailResponseTest.java
│ │ ├── DeleteEmailRequestTest.java
│ │ ├── DeleteEmailResponseTest.java
│ │ ├── EmailTest.java
│ │ ├── SendEmailRequestTest.java
│ │ ├── TelegramConnectorStatsTest.java
│ │ └── TrashEmailStatsTest.java
│ ├── EmailServerInteractionTests.java
│ ├── TrashEmailApplicationTests.java
│ └── TrashEmailResourceTest.java
└── build-and-run.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .gitignore
================================================
HELP.md
target/
mvnw
mvnw.cmd
**/.mvn/wrapper/**
### Ignore vim swp files
*.swp
### Ignore application-<enc>.yml properties
**/application-dev.yml
**/application-prod.yml
**/application-qa.yml
src/main/resources/application.yml
*.db
lib/
bin/
*.html
./EmailsToTelegramService/src/main/resources/application-qa.yml
./EmailsToTelegramService/src/main/resources/application-dev.yml
*.yml
./EmailsToTelegramService/src/main/resources/application.yml
*.dat
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
.DS_Store/*
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
================================================
FILE: .gitmodules
================================================
[submodule "TrashEmailFetchMail"]
path = TrashEmailFetchMail
url = https://github.com/TrashEmail/TrashEmailFetchMail.git
branch = master
[submodule "TrashEmailTelegramConnector"]
path = TrashEmailTelegramConnector
url = https://github.com/TrashEmail/TrashEmailTelegramConnector.git
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: Makefile
================================================
##################################################################
# Project Convenience Makefile Wrapper for Maven & Docker #
##################################################################
# This makefile is just a convenience wrapper for the Maven
# program and the docker build which is used to build packaged
# microservices for entire functionality. The actual building
# rules for this project may be found in the Maven "pom.xml"
# */Dockerfile and file located in this folder.
######################### DEFINITIONS ############################
# Define the commandline invocation of Maven if necessary:
# ifeq ($(MVN))
# MVN := mvn
# endif
MVN = mvn
DOCKER_COMPOSE=docker-compose
######################## BUILD TARGETS ###########################
clean:
cd ./TrashEmailService && $(MVN) clean
cd ./EmailsToTelegramService && $(MVN) clean
build :
echo "Building TrashEmailService ...\n"
cd ./TrashEmailService && $(MVN) -Dmaven.test.skip=true install
echo "Building EmailsToTelegramService ...\n"
cd ./EmailsToTelegramService && $(MVN) -Dmaven.test.skip=true install
echo "Building the docker-compose ...\n"
$(DOCKER_COMPOSE) build
copy :
echo $(ENV)
cp ./EmailsToTelegramServiceConfig-$(ENV).yml EmailsToTelegramService/src/main/resources/application-$(ENV).yml
cp ./TrashEmailServiceConfig-$(ENV).yml TrashEmailService/src/main/resources/application-$(ENV).yml
qa : export ENV:=qa
qa : clean copy build
dev : export ENV:=dev
dev : clean copy build
prod : export ENV:=prod
prod : clean copy build
================================================
FILE: README.md
================================================
<p align=center>
<img src="./TrashEmail.png">
</p>
[](https://travis-ci.org/TrashEmail/TrashEmail)
[](https://gitter.im/Trashemail/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)






<a target="_blank" href="https://twitter.com/intent/tweet?text=TrashEmail%20is%20open%20source%20extremely%20privacy%20focused%20disposable%2Fsemi-permanent%20email%20bot%20solution%20for%20telegram.%20By%20@sec_r0,%20%20Do%20check%20this%20out.&url=https%3A%2F%2Fgithub.com%2FTrashEmail%2FTrashEmail%2F&hashtags=privacy,osint,temp_mail,disposable_mail,telegram_bot" title="Share on Twitter"><img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Share%20on%20Twitter"></a>
### tl;dr
TrashEmail is hosted Telegram bot that can save your private email address by offering disposable email address. It can create, manage, disposable email address and link them with your telegram bot chat.
- **Where is the bot?** - [@trashemail_bot](https://t.me/trashemail_bot)
- **How can I create dispoable mail id?** - Decide a username & ask the bot :smile:
- **How many email ids can I own at a time?** - Right now, the count is **8**.
- **How can I access my emails?** - If there is an email for you, it will come to telegram :smile: Easy right.
- **Do I need to setup and remember any password?** - No Sir, that's the trick.
- **Why am I maintaining and hosting this?** - This is my first such tool for community :smile: I wanted to give something back to community. If you like the idea and wanted to contribute then you can [BuyMeACoffee](https://www.buymeacoffee.com/r0hi7)
- **How many users are currently using it?** - The information about active registered users and latest version of this service can be found here: https://trashemail.in

#### How can I use this hosted service:
- Its super easy, just see the demo below.
[](https://www.youtube.com/watch?v=DB1orBm9VCY)
### What is Disposable Temporary E-mail? And How am I different?
Forget about spam, advertising mailings, hacking and attacking robots. Keep your real mailbox clean and secure.Trashemail provides temporary(or permanent), secure, anonymous, free, disposable email address. Want to get one ? its here : [@trashemail_bot](https://t.me/trashemail_bot)
**Disposable email** - is a service that allows to receive email at a temporary(Here in case, the temporary factor is upto you) address that self-destructed after a certain time elapses. It is also known by names like : tempmail, 10minutemail, throwaway email, fake-mail or trash-mail. Many forums, Wi-Fi owners, websites and blogs ask visitors to register before they can view content, post comments or download something.
**Trashemail** is not most advanced throwaway email service but a reliable service that helps you avoid spam, stay safe and get emails delivered directly to your [@trashemail_bot](https://t.me/trashemail_bot) *Telegram bot*. And in case you are getting too many such mails, just delete the email Id :) with one click(oops command, since this is telegram bot).
There are websites that offers such sort of functionalities (like https://temp-mail.org/en/ etc) but the certain issues with such platforms:
1. Your information is safe or not you can't audit.
2. The domain keeps changing as soon as they are identified as temp-mail domains.
3. Everytime you have to visit site to get one, you can't keep the same temporary mail for long.
4. And, their business model which makes you see lot of ads in website.
Considering all of this, I decided to make a open source project out of my hobby and thought of offering it as a service to others :)
How my service is ~better~ than theirs:
1. The entire source code is open for audit, I am not interested in your data at all.
2. Right now I own a domain trashemail.in and you will get emailIds from this domain only. (Easy for you to remember).
3. The temporary time for your emailId to be alive is on you, not on the server, you can keep it permanently as well, or as long as I am able to maintain the [@trashemail_bot](https://t.me/trashemail_bot).
4. This project is out of passion, so I don't have motive of earning anything, so **No Ads**.(I am serious, I hate them too, like you)
5. I am always open to suggestion, feedback & Issues to work on.
### Let's talk about the [Source](https://github.com/r0hi7/Trashemail).
TrashEmail is Java spring-boot microservice that anyone can build locally currently with few setting to tune in and then have the entire setup running locally.
All you need to own is mail server(SMTP and IMAP), telegram bot token and `mvn` locally to build it.
Few requirements with the mailserver:
1. SMTP host should allow **Alias** creation.
2. IMAP server should support **IDLE**.
I have to update the config slightly, and will do it quickly. :)
All you need to do is clone the source, build and run, and just tell telegram that you are listening here.
```shell script
git clone https://github.com/r0hi7/Trashemail.git
cd Trashemail
# Copy EmailsToTelegramServiceConfig-sample.yml and
# TrashEmailServiceConfig-sample.yml files
# according to your environemnt
# Let's say you want to deploy it for dev env
# Then copy these files like
cp EmailsToTelegramServiceConfig-sample.yml EmailsToTelegramServiceConfig-dev.yml
cp TrashEmailServiceConfig-sample.yml TrashEmailServiceConfig-dev.yml
# Now modify the respective copied files with your configs
# Similarly, it can be deployed be "qa", "prod" environments
# Finally, run the script build-and-run.sh with env as an argument
bash build-and-run.sh dev
# If you dont want to deploy it in docker-compose, then
# Use Makefile directly
# It will create targets for EmailsToTelegramService and TrashEmailService respectively
make dev
```
Dev configs may look like this:
`EmailsToTelegramServiceConfig-dev.yml`
```yaml
# Email Server IMAP and SMTP configuration
# SMTP server should support Alias creation and deletion
# IMAP server should support IDLE
trashemail:
host: trash-email-service
port: 9090
path: /getChatId/
imap-client-service:
telegram:
url: https://api.telegram.org/bot
bot-token: xxxxxxxxxxxxxxxxxxxxxx
size: 4096
imap:
host: trashemail.in
port: 993
email: demo@trashemail.in
password: changeme
emails:
hostPath: http://127.0.0.1:8000/
downloadPath: /opt/EmailsToTelegramService/mails/
# main will specify springboot application to
# no start any tomcat server, which is not even
# required for emailservice.
spring:
application:
name: EmailsToTelegramService
main:
web-application-type: none
```
`TrashEmailServiceConfig-dev.yml`
```yaml
# Tomcat server settings
server:
port: 9090
#Email server configuration for SMTP alias creation
email-server:
hosts:
- trashemail.in
- thromail.com
- humblemail.com
admin-email: contact@trashemail.in
admin-password: sample
add-url: https://trashemail.in/admin/mail/aliases/add
remove-url: https://trashemail.in/admin/mail/aliases/remove
target-alias: demo@trashemail.in
# Sample config for connecting with mysql-docker
spring:
datasource:
url: jdbc:mysql://mysql:3306/trashemail
username: root
password: changeme
driver-class-name: com.mysql.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: update
show-sql: true
application:
name: Trashemail
# Trashemail app server settings
trashemail:
max-emails-per-user: 4
# Logger settings
logging:
level:
io:
github:
trashemail: debug
```
1. This code will spin up the service at `localhost:9090/telegram/new-message` endpoint.
2. Now will have to expose this service to internet, and there are options like : `ngrok`, `dataplicity`, `localtunnel` etc.
* Start `ngrok`with http on port 9090
* Get the `ngrok` https url
3. DB is taken care by `mysql`
4. Get a bot for you from, [Telegram Bot Father](https://telegram.me/BotFather)
5. The last step is important, tell telegram that where you are listening :). Set up the `webhook`, this `webhook` will tell telegram where to send the bot incoming requests
```shell script
curl -F "url=https://<YOUR_DOMAIN>/telegram/new-message" https://api.telegram.org/bot<BOT_TOKEN>/setWebhook
```
6. And you are done.
### How It Works
1. For this bot to work, you need existing SMTP, IMAP setup.
1. SMTP with Alias creation
2. IMAP with IDLE enabled
3. As user, requests for creation,
2. It fools the user, that it created an email Id rather it creates an alias to exiting ID.
1. Why Alais, as IMAP needs to poll right, for incoming mails? This is how it is engineered.
3. Runs a background async service to poll IMAP server.
4. As soon as mail is fetched, the target is identified and telegram message is sent.
I have tried to engineer this service to be reliable, in case if you find any issues with the reliability(or with anything else), please feel free to drop in a PR. I would be happy to review and merge.
### Sponsors
1. Two domains [thromail.com](thromail.com) & [humblemail.com](humblemail.com) are proudly donated by [zlipa.com](https://zlipa.com/). [Zlipa](https://zlipa.com/) offers domains names for startups, bootstrapper etc with 10X lesser market price. Exciting right? Just checkout once.
2. If you like the idea, then buy me a coffee, I will get caffine in my blood and to spend extra nights to make this product secure, up and running :smile:
<a href="https://www.buymeacoffee.com/r0hi7" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/arial-blue.png" alt="Buy Me A Coffee" style="height: 25.5px !important;width: 72px !important;" ></a>
3. Or you can drop in a :star:, this motivates me.
### Credits

### Infrastructure model

================================================
FILE: TrashEmailService/.gitignore
================================================
HELP.md
target/
mvnw
mvnw.cmd
**/.mvn/wrapper/**
### Ignore vim swp files
*.swp
### Ignore application-<enc>.yml properties
**/application-dev.yml
**/application-prod.yml
**/application-qa.yml
src/main/resources/application.yml
*.db
lib/
bin/
*.html
./EmailsToTelegramService/src/main/resources/application-qa.yml
*.yml
./EmailsToTelegramService/src/main/resources/application.yml
*.dat
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
.DS_Store/*
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
================================================
FILE: TrashEmailService/Dockerfile
================================================
FROM openjdk:8-jre-alpine
ARG SPRING_PROFILES_ACTIVE
RUN mkdir -p /opt/TrashEmailService/
COPY ./target/*.jar /opt/TrashEmailService/trashemailservice.jar
WORKDIR /opt/TrashEmailService/
EXPOSE 9090
ENTRYPOINT ["java","-jar","trashemailservice.jar"]
================================================
FILE: TrashEmailService/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.github</groupId>
<artifactId>TrashEmailService</artifactId>
<version>3.0.0</version>
<name>TrashEmailService</name>
<description>Springboot miscroservice - heart of Telegram @trashemail_bot</description>
<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/r0hi7/Trashemail</url>
</repository>
</distributionManagement>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.4.0</version>
</dependency>
<!-- Spring boot Thymeleaf for serving HTML pages -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-thymeleaf</artifactId>-->
<!-- </dependency>-->
<!-- Comment H2
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
<version>1.4.199</version>
</dependency>
-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/Configurations/EmailServerConfig.java
================================================
package io.github.trashemail.Configurations;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
@ConfigurationProperties(prefix = "email-server")
@Getter @Setter @NoArgsConstructor
public class EmailServerConfig {
private List<String> hosts;
private String adminEmail;
private String adminPassword;
private String addUrl;
private String removeUrl;
private List<String> targetAlias;
@Override public String toString() {
return "EmailServerConfig{" +
"hosts=" + hosts +
", adminEmail='" + adminEmail + '\'' +
", addUrl='" + addUrl + '\'' +
", removeUrl='" + removeUrl + '\'' +
", targetAlias='" + targetAlias + '\'' +
'}';
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/Configurations/TrashEmailConfig.java
================================================
package io.github.trashemail.Configurations;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@Configuration
@ConfigurationProperties(prefix = "trashemail")
public class TrashEmailConfig {
private String version;
private List<String> connectorURLs;
@Override public String toString() {
return "TrashEmailConfig{" +
"version='" + version + '\'' +
'}';
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/ConnectorStats.java
================================================
package io.github.trashemail.DTO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class ConnectorStats {
private String connectorName;
private Long activeUsers;
private Long totalNumberOfUsers;
private Long activeEmailIds;
private Long totalNumberOfEmailIds;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/CreateEmailRequest.java
================================================
package io.github.trashemail.DTO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class CreateEmailRequest {
private String source;
private String destination;
private String destinationType;
private String emailId;
private Boolean isActive;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/CreateEmailResponse.java
================================================
package io.github.trashemail.DTO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class CreateEmailResponse {
private Boolean created;
private String message;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/DeleteEmailRequest.java
================================================
package io.github.trashemail.DTO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class DeleteEmailRequest {
private String emailId;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/DeleteEmailResponse.java
================================================
package io.github.trashemail.DTO;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class DeleteEmailResponse {
private String emailId;
private Boolean isDeleted;
private String error;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/Email.java
================================================
package io.github.trashemail.DTO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.Date;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
public class Email {
private String emailId;
private String message;
private Date arrived;
private String emailURI;
private String emailDownloadPath;
private List<String> attachmentsPaths;
public Email(SendEmailRequest sendEmailRequest){
this.arrived = new Date();
this.emailId = sendEmailRequest.getEmailId();
this.message = sendEmailRequest.getMessage();
this.emailURI = sendEmailRequest.getEmailURI();
this.emailDownloadPath = sendEmailRequest.getEmailDownloadPath();
this.attachmentsPaths = sendEmailRequest.getAttachmentsPaths();
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/SendEmailRequest.java
================================================
package io.github.trashemail.DTO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
public class SendEmailRequest {
private String emailId;
private String message;
private String emailURI;
private String emailDownloadPath;
private List<String> attachmentsPaths;
@Override public String toString() {
return "SendEmailRequest{" +
"emailId='" + emailId + '\'' +
", message='" + message + '\'' +
", emailURI='" + emailURI + '\'' +
", emailDownloadPath='" + emailDownloadPath + '\'' +
", attachmentsPaths=" + attachmentsPaths +
'}';
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/TelegramConnectorStats.java
================================================
package io.github.trashemail.DTO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class TelegramConnectorStats {
private Long activeUsers;
private Long totalNumberOfUsers;
private Long activeEmailIds;
private Long totalNumberOfEmailIds;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/TrashEmailStats.java
================================================
package io.github.trashemail.DTO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
import java.util.Map;
@Getter
@Setter
@NoArgsConstructor
public class TrashEmailStats {
private Long numberOfUsers;
private Long numberOfEmailsRegistered;
private Map<String, Long> domainsToNumbers;
private Long emailIdsCreatedToday;
private List<Long> emailIdsCreatedInWeek;
private String version;
private Long numberOfEmailsProcessed;
private Long totalNumberOfUsers;
private List<ConnectorStats> connectorStats;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/EmailServerInteraction.java
================================================
package io.github.trashemail;
import io.github.trashemail.Configurations.EmailServerConfig;
import io.github.trashemail.exceptions.EmailAliasNotCreatedExecption;
import io.github.trashemail.models.EmailAllocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
@Component("EmailServerInteraction")
public class EmailServerInteraction {
@Autowired
private EmailServerConfig emailServerConfig;
@Autowired
RestTemplate restTemplate;
private static final Logger log = LoggerFactory.getLogger(
EmailServerInteraction.class);
public String createEmailId(EmailAllocation emailAllocation)
throws HttpClientErrorException, EmailAliasNotCreatedExecption {
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(
emailServerConfig.getAdminEmail(),
emailServerConfig.getAdminPassword()
);
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> data = new LinkedMultiValueMap<String, String>();
data.add("address", emailAllocation.getEmailId());
data.add("forwards_to", emailAllocation.getForwardsTo());
HttpEntity<MultiValueMap<String, String>> request =
new HttpEntity<MultiValueMap<String, String>>(data, headers);
ResponseEntity response = restTemplate.postForEntity(
emailServerConfig.getAddUrl(),
request,
String.class);
if(response.getStatusCode() == HttpStatus.OK){
return "Email ID : *"+emailAllocation.getEmailId()+"* "+
"successfully Created :)";
}
log.error(response.getStatusCode().toString() + response.getBody());
throw new EmailAliasNotCreatedExecption(response.getBody().toString());
}
public boolean deleteEmailId(EmailAllocation emailAllocation) {
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(
emailServerConfig.getAdminEmail(),
emailServerConfig.getAdminPassword()
);
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> data = new LinkedMultiValueMap<String, String>();
data.add("address", emailAllocation.getEmailId());
HttpEntity<MultiValueMap<String, String>> request =
new HttpEntity<MultiValueMap<String, String>>(data, headers);
// RestTemplate restTemplate = new RestTemplate();
ResponseEntity response = restTemplate.postForEntity(
emailServerConfig.getRemoveUrl(),
request,
String.class);
if(response.getStatusCode() == HttpStatus.OK){
return true;
}
else if(response.getStatusCode() == HttpStatus.BAD_REQUEST){
return false;
}
return false;
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/Respositories/FreeUserIdRepository.java
================================================
package io.github.trashemail.Respositories;
import io.github.trashemail.models.FreeUserId;
import org.springframework.data.repository.CrudRepository;
public interface FreeUserIdRepository
extends CrudRepository<FreeUserId, Integer> {
public FreeUserId findTopByOrderByIdAsc();
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/Respositories/UsedUserIdRepository.java
================================================
package io.github.trashemail.Respositories;
import io.github.trashemail.models.UsedUserId;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.time.LocalDateTime;
import java.util.List;
public interface UsedUserIdRepository
extends CrudRepository<UsedUserId, Integer> {
public List<UsedUserId> findByChatIdAndIsActiveTrue(long chatId);
public UsedUserId findByUserId(String userId);
public List<UsedUserId> findAllByCreateDateTimeBetween(
LocalDateTime begin, LocalDateTime end);
@Query(value = "SELECT * FROM used_user_ids " +
"where create_date_time <= " +
"NOW() - INTERVAL 10 MINUTE", nativeQuery = true)
public List<UsedUserId> getUserIdsCreatedBeforeTenMinutes();
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/TrashEmailApplication.java
================================================
package io.github.trashemail;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableAsync
public class TrashEmailApplication {
public static void main(String[] args) {
SpringApplication.run(TrashEmailApplication.class, args);
}
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/TrashEmailResource.java
================================================
package io.github.trashemail;
import io.github.trashemail.Configurations.EmailServerConfig;
import io.github.trashemail.Configurations.TrashEmailConfig;
import io.github.trashemail.DTO.*;
import io.github.trashemail.exceptions.EmailAlreadyExsitExecption;
import io.github.trashemail.exceptions.EmailNotFoundExecption;
import io.github.trashemail.models.EmailAllocation;
import io.github.trashemail.repositories.EmailAllocationRepository;
import io.github.trashemail.repositories.EmailCounterRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.*;
@RestController
public class TrashEmailResource {
@Autowired
EmailCounterRepository emailCounterRepository;
@Autowired
EmailAllocationRepository emailAllocationRepository;
@Autowired
EmailServerConfig emailServerConfig;
@Autowired
TrashEmailConfig trashemailConfig;
@Autowired
EmailServerInteraction emailServerInteraction;
@Autowired
RestTemplate restTemplate;
private static final Logger log = LoggerFactory.getLogger(
TrashEmailResource.class);
@PostMapping(value = "/create")
public ResponseEntity<CreateEmailResponse> createEmailId(@RequestBody CreateEmailRequest createEmailRequest){
CreateEmailResponse createEmailResponse = new CreateEmailResponse();
try{
EmailAllocation checkIfExist = emailAllocationRepository.findByEmailIdAndIsActiveTrue(
createEmailRequest.getEmailId());
if(checkIfExist != null)
throw new EmailAlreadyExsitExecption();
EmailAllocation emailAllocation = new EmailAllocation(createEmailRequest);
EmailAllocation existOlder = emailAllocationRepository.findByEmailIdAndDestinationAndDestinationType(
emailAllocation.getEmailId(),
emailAllocation.getDestination(),
emailAllocation.getDestinationType()
);
if (existOlder != null)
emailAllocation = existOlder;
else {
Random random = new Random();
emailAllocation.setForwardsTo(
emailServerConfig
.getTargetAlias()
.get(random.nextInt(emailServerConfig.getTargetAlias().size())));
}
emailAllocation.setIsActive(true);
emailServerInteraction.createEmailId(emailAllocation);
createEmailResponse.setCreated(true);
createEmailResponse.setMessage("Email Address created");
emailAllocationRepository.save(emailAllocation);
return new ResponseEntity<>(createEmailResponse, HttpStatus.CREATED);
}catch(Exception exception){
createEmailResponse.setMessage(exception.getMessage());
createEmailResponse.setCreated(false);
}
return new ResponseEntity<>(createEmailResponse, HttpStatus.BAD_REQUEST);
}
@PostMapping(value = "/delete")
public ResponseEntity<DeleteEmailResponse> deleteEmailId(@RequestBody DeleteEmailRequest deleteEmailRequest){
EmailAllocation emailAllocation = emailAllocationRepository.findByEmailIdAndIsActiveTrue(
deleteEmailRequest.getEmailId());
DeleteEmailResponse deleteEmailResponse = new DeleteEmailResponse();
try{
if(emailAllocation == null)
throw new EmailNotFoundExecption();
emailServerInteraction.deleteEmailId(emailAllocation);
emailAllocation.setIsActive(false);
emailAllocationRepository.save(emailAllocation);
deleteEmailResponse.setEmailId(deleteEmailRequest.getEmailId());
deleteEmailResponse.setIsDeleted(true);
return new ResponseEntity<>(deleteEmailResponse, HttpStatus.OK);
}catch (Exception e){
deleteEmailResponse.setIsDeleted(false);
deleteEmailResponse.setError(e.getMessage());
}
return new ResponseEntity<>(deleteEmailResponse, HttpStatus.BAD_REQUEST);
}
@PostMapping(value = "/sendMail")
public String sendMail(@RequestBody SendEmailRequest sendEmailRequest){
emailCounterRepository.updateCount();
EmailAllocation emailAllocation = emailAllocationRepository.findByEmailIdAndIsActiveTrue(
sendEmailRequest.getEmailId());
if(emailAllocation == null){
return "Mail target not active";
}
String mailTargetType = emailAllocation.getDestinationType();
if(mailTargetType.equals("url") || mailTargetType.equals("telegram")){
/*
Create a post request
*/
String targetURI = emailAllocation.getDestination();
Email email = new Email(sendEmailRequest);
ResponseEntity response = restTemplate.postForEntity(
targetURI,
email,
String.class
);
return (String) response.getBody();
}
else if(mailTargetType.equals("email")){
/*
Send Email
*/
}
return "Mail Sent.";
}
@GetMapping(value = "/stats")
public TrashEmailStats presentDashBoard(){
TrashEmailStats trashemailStats = new TrashEmailStats();
trashemailStats.setVersion(trashemailConfig.getVersion());
List<ConnectorStats> connectorStats = new ArrayList<>();
/*
Get Stats from each connector
*/
for(String connectorURL : trashemailConfig.getConnectorURLs()){
connectorStats.add(
restTemplate.getForEntity(connectorURL + "/stats/", ConnectorStats.class).getBody()
);
}
trashemailStats.setConnectorStats(connectorStats);
Map<String, Long> domainCount = new HashMap<String, Long>();
for(String domain: emailServerConfig.getHosts()){
Long countForDomain = (
(Integer) emailAllocationRepository.findByEmailIdEndsWith(domain).size()
).longValue();
domainCount.put(domain, countForDomain);
}
trashemailStats.setDomainsToNumbers(domainCount);
trashemailStats.setEmailIdsCreatedToday(emailAllocationRepository.getEmailIdsCreatedTodayCount());
Calendar calendar = Calendar.getInstance();
Date today = calendar.getTime();
calendar.add(Calendar.DAY_OF_MONTH, -7);
Date sevenDaysBefore = calendar.getTime();
trashemailStats.setEmailIdsCreatedInWeek(
emailAllocationRepository.getEmailIdsCreatedInWeek(
today,
sevenDaysBefore
)
);
trashemailStats.setNumberOfEmailsProcessed(
emailCounterRepository.count()
);
return trashemailStats;
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/exceptions/EmailAliasNotCreatedExecption.java
================================================
package io.github.trashemail.exceptions;
public class EmailAliasNotCreatedExecption extends Exception {
public EmailAliasNotCreatedExecption(String message){
super(message);
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/exceptions/EmailAlreadyExsitExecption.java
================================================
package io.github.trashemail.exceptions;
public class EmailAlreadyExsitExecption extends Exception {
public EmailAlreadyExsitExecption(){
super("Email Address already taken");
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/exceptions/EmailNotFoundExecption.java
================================================
package io.github.trashemail.exceptions;
public class EmailNotFoundExecption extends Exception {
public EmailNotFoundExecption(){
super("Email not allocated to anyone.");
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/models/EmailAllocation.java
================================================
package io.github.trashemail.models;
import io.github.trashemail.DTO.CreateEmailRequest;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
@Getter
@Setter
@NoArgsConstructor
@Table(name="email_allocated")
@Entity
public class EmailAllocation {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String emailId;
private String forwardsTo;
private Boolean isActive;
private String source;
private String destination;
private String destinationType;
@CreationTimestamp
private LocalDateTime createDateTime;
public EmailAllocation(CreateEmailRequest emailRequest){
this.emailId = emailRequest.getEmailId();
this.isActive = true;
this.source = emailRequest.getSource();
this.destination = emailRequest.getDestination();
this.destinationType = emailRequest.getDestinationType();
}
@Override public String toString() {
return "EmailAllocation{" +
"id=" + id +
", emailId='" + emailId + '\'' +
", forwardsTo='" + forwardsTo + '\'' +
", isActive=" + isActive +
", source='" + source + '\'' +
", destination='" + destination + '\'' +
", destinationType='" + destinationType + '\'' +
", createDateTime=" + createDateTime +
'}';
}
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/models/EmailCounter.java
================================================
package io.github.trashemail.models;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "emailCounter")
public class EmailCounter {
@Id
@GeneratedValue
private Integer id;
private Integer count;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/models/FreeUserId.java
================================================
package io.github.trashemail.models;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "free_user_ids")
public class FreeUserId {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String userId;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/models/UsedUserId.java
================================================
package io.github.trashemail.models;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "used_user_ids")
public class UsedUserId {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long chatId;
private Boolean isActive;
private String userId;
@CreationTimestamp
private LocalDateTime createDateTime;
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/repositories/EmailAllocationRepository.java
================================================
package io.github.trashemail.repositories;
import io.github.trashemail.models.EmailAllocation;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import java.util.Date;
import java.util.List;
public interface EmailAllocationRepository
extends CrudRepository<EmailAllocation, Long> {
EmailAllocation findByEmailIdAndIsActiveTrue(String emailId);
EmailAllocation findByEmailIdAndDestinationAndDestinationType(String emailId,
String destination,
String destination_type);
List<EmailAllocation> findByEmailIdEndsWith(String domain);
@Query(
value = "SELECT count(user.emailId) FROM EmailAllocation user " +
"WHERE DATE (user.createDateTime) = CURDATE() "
) long getEmailIdsCreatedTodayCount();
/*
In JPA DB dialects for date manipulations are not good, so using java
based approach.
*/
@Query(
value = "SELECT count(user.emailId) FROM EmailAllocation user " +
"WHERE DATE(user.createDateTime) >= :oneWeekOldDate and " +
"DATE(user.createDateTime) <= :today " +
"GROUP BY DATE(user.createDateTime) " +
"ORDER BY DATE(user.createDateTime)"
) List<Long> getEmailIdsCreatedInWeek(
@Param("today") Date currDate,
@Param("oneWeekOldDate") Date oneWeekOldDate
);
}
================================================
FILE: TrashEmailService/src/main/java/io/github/trashemail/repositories/EmailCounterRepository.java
================================================
package io.github.trashemail.repositories;
import io.github.trashemail.models.EmailCounter;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import javax.transaction.Transactional;
public interface EmailCounterRepository
extends CrudRepository<EmailCounter, Integer> {
@Transactional
@Modifying
@Query(value = "UPDATE EmailCounter ec set ec.count = ec.count + 1 where " +
"ec.id = 1")
public void updateCount();
@Query(value = "select ec.count from EmailCounter ec where ec.id=1")
public long count();
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/ConnectorStatsTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class ConnectorStatsTest {
private ConnectorStats connectorStats;
@BeforeEach
public void setUp() {
connectorStats = new ConnectorStats();
}
@Test
public void gettersNullTest() {
assertNull(connectorStats.getConnectorName());
assertNull(connectorStats.getActiveUsers());
assertNull(connectorStats.getTotalNumberOfUsers());
assertNull(connectorStats.getActiveEmailIds());
assertNull(connectorStats.getTotalNumberOfEmailIds());
}
@Test
public void settersTest() {
String connectorName = "Name";
connectorStats.setConnectorName(connectorName);
assertEquals(connectorName, connectorStats.getConnectorName());
Long activeUsers = new Long(100);
connectorStats.setActiveUsers(activeUsers);
assertEquals(activeUsers, connectorStats.getActiveUsers());
Long totalNumberOfUsers = new Long(54580);
connectorStats.setTotalNumberOfUsers(totalNumberOfUsers);
assertEquals(totalNumberOfUsers, connectorStats.getTotalNumberOfUsers());
Long activeEmailIds = new Long(24);
connectorStats.setActiveEmailIds(activeEmailIds);
assertEquals(activeEmailIds, connectorStats.getActiveEmailIds());
Long totalNumberOfEmailIds = new Long(22300);
connectorStats.setTotalNumberOfEmailIds(totalNumberOfEmailIds);
assertEquals(totalNumberOfEmailIds, connectorStats.getTotalNumberOfEmailIds());
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/CreateEmailRequestTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class CreateEmailRequestTest {
private CreateEmailRequest createEmailRequest;
@BeforeEach
public void setUp() {
createEmailRequest = new CreateEmailRequest();
}
@Test
public void gettersNullTest() {
assertNull(createEmailRequest.getSource());
assertNull(createEmailRequest.getDestination());
assertNull(createEmailRequest.getDestinationType());
assertNull(createEmailRequest.getEmailId());
assertNull(createEmailRequest.getIsActive());
}
@Test
public void settersTest() {
String source = "source";
createEmailRequest.setSource(source);
assertEquals(source, createEmailRequest.getSource());
String destination = "destination";
createEmailRequest.setDestination(destination);
assertEquals(destination, createEmailRequest.getDestination());
String destinationType = "destinationType";
createEmailRequest.setDestinationType(destinationType);
assertEquals(destinationType, createEmailRequest.getDestinationType());
String emailId = "emailId";
createEmailRequest.setEmailId(emailId);
assertEquals(emailId, createEmailRequest.getEmailId());
boolean isActive = true;
createEmailRequest.setIsActive(isActive);
assertEquals(isActive, createEmailRequest.getIsActive());
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/CreateEmailResponseTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class CreateEmailResponseTest {
private CreateEmailResponse createEmailResponse;
@BeforeEach
public void setUp() {
createEmailResponse = new CreateEmailResponse();
}
@Test
public void gettersNullTest() {
assertNull(createEmailResponse.getCreated());
assertNull(createEmailResponse.getMessage());
}
@Test
public void settersTest() {
boolean created = true;
createEmailResponse.setCreated(created);
assertEquals(created, createEmailResponse.getCreated());
String message = "message";
createEmailResponse.setMessage(message);
assertEquals(message, createEmailResponse.getMessage());
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/DeleteEmailRequestTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class DeleteEmailRequestTest {
private DeleteEmailRequest deleteEmailRequest;
@BeforeEach
public void setUp() {
deleteEmailRequest = new DeleteEmailRequest();
}
@Test
public void getterNullTest() {
assertNull(deleteEmailRequest.getEmailId());
}
@Test
public void setterTest() {
String emailId = "emailId";
deleteEmailRequest.setEmailId(emailId);
assertEquals(emailId, deleteEmailRequest.getEmailId());
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/DeleteEmailResponseTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class DeleteEmailResponseTest {
private DeleteEmailResponse deleteEmailResponse;
@BeforeEach
public void setUp() {
deleteEmailResponse = new DeleteEmailResponse();
}
@Test
public void settersTest() {
String emailId = "emailId";
deleteEmailResponse.setEmailId(emailId);
assertEquals(emailId, deleteEmailResponse.getEmailId());
Boolean isDeleted = true;
deleteEmailResponse.setIsDeleted(isDeleted);
assertEquals(isDeleted, deleteEmailResponse.getIsDeleted());
String error = "error";
deleteEmailResponse.setError(error);
assertEquals(error, deleteEmailResponse.getError());
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/EmailTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import java.util.Date;
import java.util.List;
import java.util.Arrays;
public class EmailTest {
private Email email;
private SendEmailRequest sendEmailRequest;
@BeforeEach
public void setUp() {
sendEmailRequest = mock(SendEmailRequest.class);
email = new Email(sendEmailRequest);
}
@Test
public void constructorTest() {
assertNotNull(email.getArrived());
assertEquals(email.getEmailId(), sendEmailRequest.getEmailId());
assertEquals(email.getMessage(), sendEmailRequest.getMessage());
assertEquals(email.getEmailURI(), sendEmailRequest.getEmailURI());
assertEquals(email.getEmailDownloadPath(), sendEmailRequest.getEmailDownloadPath());
assertEquals(email.getAttachmentsPaths(), sendEmailRequest.getAttachmentsPaths());
}
@Test
public void settersTest() {
Date date = mock(Date.class);
email.setArrived(date);
assertEquals(date, email.getArrived());
String emailId = "hola@gmail.com";
email.setEmailId(emailId);
assertEquals(emailId, email.getEmailId());
String message = "hola";
email.setMessage(message);
assertEquals(message, email.getMessage());
String emailURI = "hola@gmail.com";
email.setEmailURI(emailURI);
assertEquals(emailURI, email.getEmailURI());
String emailDownloadPath = "www.direccion.com";
email.setEmailDownloadPath(emailDownloadPath);
assertEquals(emailDownloadPath, email.getEmailDownloadPath());
List<String> attachmentsPaths = Arrays.asList("at1", "at2", "at3");
email.setAttachmentsPaths(attachmentsPaths);
assertEquals(attachmentsPaths, email.getAttachmentsPaths());
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/SendEmailRequestTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class SendEmailRequestTest {
private SendEmailRequest sendEmailRequest;
@BeforeEach
public void setUp() {
sendEmailRequest = new SendEmailRequest();
}
@Test
public void gettersNullTest() {
assertNull(sendEmailRequest.getEmailId());
assertNull(sendEmailRequest.getMessage());
assertNull(sendEmailRequest.getEmailURI());
assertNull(sendEmailRequest.getEmailDownloadPath());
assertNull(sendEmailRequest.getAttachmentsPaths());
}
@Test
public void settersTest() {
String emailId = "emailId";
sendEmailRequest.setEmailId(emailId);
assertEquals(emailId, sendEmailRequest.getEmailId());
String message = "message";
sendEmailRequest.setMessage(message);
assertEquals(message, sendEmailRequest.getMessage());
String emailURI = "emailURI";
sendEmailRequest.setEmailURI(emailURI);
assertEquals(emailURI, sendEmailRequest.getEmailURI());
String emailDownloadPath = "emailDownloadPath";
sendEmailRequest.setEmailDownloadPath(emailDownloadPath);
assertEquals(emailDownloadPath, sendEmailRequest.getEmailDownloadPath());
List<String> attachmentsPaths = Arrays.asList("att1", "att2");
sendEmailRequest.setAttachmentsPaths(attachmentsPaths);
assertEquals(attachmentsPaths, sendEmailRequest.getAttachmentsPaths());
}
@Test
public void toStringTest() {
// Set up
String emailId = "emailId";
sendEmailRequest.setEmailId(emailId);
String message = "message";
sendEmailRequest.setMessage(message);
String emailURI = "emailURI";
sendEmailRequest.setEmailURI(emailURI);
String emailDownloadPath = "emailDownloadPath";
sendEmailRequest.setEmailDownloadPath(emailDownloadPath);
List<String> attachmentsPaths = Arrays.asList("att1", "att2");
sendEmailRequest.setAttachmentsPaths(attachmentsPaths);
String texto = "SendEmailRequest{" +
"emailId='" + sendEmailRequest.getEmailId() + '\'' +
", message='" + sendEmailRequest.getMessage() + '\'' +
", emailURI='" + sendEmailRequest.getEmailURI() + '\'' +
", emailDownloadPath='" + sendEmailRequest.getEmailDownloadPath()+ '\'' +
", attachmentsPaths=" + sendEmailRequest.getAttachmentsPaths() +
'}';
String resultado = sendEmailRequest.toString();
assertEquals(texto, resultado);
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/TelegramConnectorStatsTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class TelegramConnectorStatsTest {
private TelegramConnectorStats telegramConnectorStats;
@BeforeEach
public void setUp() {
telegramConnectorStats = new TelegramConnectorStats();
}
@Test
public void gettersNullTest() {
assertNull(telegramConnectorStats.getActiveUsers());
assertNull(telegramConnectorStats.getTotalNumberOfUsers());
assertNull(telegramConnectorStats.getActiveEmailIds());
assertNull(telegramConnectorStats.getTotalNumberOfEmailIds());
}
@Test
public void settersTest() {
Long activeUsers = new Long(20);
telegramConnectorStats.setActiveUsers(activeUsers);
assertEquals(activeUsers, telegramConnectorStats.getActiveUsers());
Long totalNumberOfUsers = new Long(150);
telegramConnectorStats.setTotalNumberOfUsers(totalNumberOfUsers);
assertEquals(totalNumberOfUsers, telegramConnectorStats.getTotalNumberOfUsers());
Long activeEmailIds = new Long(15);
telegramConnectorStats.setActiveEmailIds(activeEmailIds);
assertEquals(activeEmailIds, telegramConnectorStats.getActiveEmailIds());
Long totalNumberOfEmailIds = new Long(100);
telegramConnectorStats.setTotalNumberOfEmailIds(totalNumberOfEmailIds);
assertEquals(totalNumberOfEmailIds, telegramConnectorStats.getTotalNumberOfEmailIds());
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/TrashEmailStatsTest.java
================================================
package io.github.trashemail.DTO;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
public class TrashEmailStatsTest {
private TrashEmailStats trashEmailStats;
@BeforeEach
public void setUp() {
trashEmailStats = new TrashEmailStats();
}
@Test
public void gettersNullTest() {
assertNull(trashEmailStats.getNumberOfUsers());
assertNull(trashEmailStats.getNumberOfEmailsRegistered());
assertNull(trashEmailStats.getDomainsToNumbers());
assertNull(trashEmailStats.getEmailIdsCreatedToday());
assertNull(trashEmailStats.getEmailIdsCreatedInWeek());
assertNull(trashEmailStats.getVersion());
assertNull(trashEmailStats.getNumberOfEmailsProcessed());
assertNull(trashEmailStats.getTotalNumberOfUsers());
assertNull(trashEmailStats.getConnectorStats());
}
@Test
public void settersTest() {
Long numberOfUsers = 15l;
trashEmailStats.setNumberOfUsers(numberOfUsers);
assertEquals(numberOfUsers, trashEmailStats.getNumberOfUsers());
Long numberOfEmailsRegistered = 100l;
trashEmailStats.setNumberOfEmailsRegistered(numberOfEmailsRegistered);
assertEquals(numberOfEmailsRegistered, trashEmailStats.getNumberOfEmailsRegistered());
Map<String, Long> domainsToNumbers = new HashMap<String, Long>();
domainsToNumbers.put("domain1", 15l);
domainsToNumbers.put("domain2", 25l);
trashEmailStats.setDomainsToNumbers(domainsToNumbers);
assertEquals(domainsToNumbers, trashEmailStats.getDomainsToNumbers());
Long emailIdsCreatedToday = 4l;
trashEmailStats.setEmailIdsCreatedToday(emailIdsCreatedToday);;
assertEquals(emailIdsCreatedToday, trashEmailStats.getEmailIdsCreatedToday());
List<Long> emailIdsCreatedInWeek = Arrays.asList(4l, 4l, 6l, 7l, 10l);
trashEmailStats.setEmailIdsCreatedInWeek(emailIdsCreatedInWeek);
assertEquals(emailIdsCreatedInWeek, trashEmailStats.getEmailIdsCreatedInWeek());
String version = "version";
trashEmailStats.setVersion(version);
assertEquals(version, trashEmailStats.getVersion());
Long numberOfEmailsProcessed = 70l;
trashEmailStats.setNumberOfEmailsProcessed(numberOfEmailsProcessed);
assertEquals(numberOfEmailsProcessed, trashEmailStats.getNumberOfEmailsProcessed());
Long totalNumberOfUsers = 1000l;
trashEmailStats.setTotalNumberOfUsers(totalNumberOfUsers);
assertEquals(totalNumberOfUsers, trashEmailStats.getTotalNumberOfUsers());
ConnectorStats connectorStats1 = mock(ConnectorStats.class);
ConnectorStats connectorStats2 = mock(ConnectorStats.class);
List<ConnectorStats> connectorStats = Arrays.asList(connectorStats1, connectorStats2);
trashEmailStats.setConnectorStats(connectorStats);
assertEquals(connectorStats, trashEmailStats.getConnectorStats());
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/EmailServerInteractionTests.java
================================================
package io.github.trashemail;
import io.github.trashemail.Configurations.EmailServerConfig;
import io.github.trashemail.exceptions.EmailAliasNotCreatedExecption;
import io.github.trashemail.models.EmailAllocation;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class EmailServerInteractionTests {
@InjectMocks
private EmailServerInteraction emailServerInteraction;
@Mock
private EmailServerConfig emailServerConfig;
@Mock
private RestTemplate restTemplate;
private static EmailAllocation emailAllocation;
@BeforeAll
static void setUpBeforeClass() {
emailAllocation = new EmailAllocation();
emailAllocation.setEmailId("a@a.com");
emailAllocation.setEmailId("emailid@a.com");
emailAllocation.setForwardsTo("forwardsto@a.com");
}
@BeforeEach
void setUpBefore() {
when(emailServerConfig.getAdminEmail()).thenReturn("admin@a.com");
when(emailServerConfig.getAdminPassword()).thenReturn("password");
}
@AfterEach
void teardown() {
emailServerConfig = null;
restTemplate = null;
}
@Test
void testCreateEmail() throws EmailAliasNotCreatedExecption {
when(emailServerConfig.getAddUrl()).thenReturn("www.addurl.com");
when(restTemplate.postForEntity(Mockito.anyString(), any(HttpEntity.class), any(Class.class)))
.thenReturn(ResponseEntity.ok(""));
String actual = emailServerInteraction.createEmailId(emailAllocation);
assertEquals("Email ID : *emailid@a.com* successfully Created :)", actual);
}
@Test
void testCreateEmailException() throws EmailAliasNotCreatedExecption {
when(emailServerConfig.getAddUrl()).thenReturn("www.addurl.com");
when(restTemplate.postForEntity(Mockito.anyString(), any(HttpEntity.class), any(Class.class)))
.thenReturn(ResponseEntity.badRequest().body(""));
assertThrows(EmailAliasNotCreatedExecption.class, () -> emailServerInteraction.createEmailId(emailAllocation));
}
@Test
@DisplayName("Delete email with 200 response")
void testDeleteEmailId() {
when(emailServerConfig.getRemoveUrl()).thenReturn("www.removeurl.com");
when(restTemplate.postForEntity(Mockito.anyString(), any(HttpEntity.class), any(Class.class)))
.thenReturn(ResponseEntity.ok(""));
boolean actual = emailServerInteraction.deleteEmailId(emailAllocation);
assertTrue(actual);
}
@Test
@DisplayName("Delete email with 400 response")
void testDeleteEmailIdBadRequest() {
when(emailServerConfig.getRemoveUrl()).thenReturn("www.removeurl.com");
when(restTemplate.postForEntity(Mockito.anyString(), any(HttpEntity.class), any(Class.class)))
.thenReturn(new ResponseEntity(HttpStatus.BAD_REQUEST));
boolean actual = emailServerInteraction.deleteEmailId(emailAllocation);
assertFalse(actual);
}
@Test
@DisplayName("Delete email with 500 response")
void testDeleteEmailIdBadRequestOtherStatusCode() {
when(emailServerConfig.getRemoveUrl()).thenReturn("www.removeurl.com");
when(restTemplate.postForEntity(Mockito.anyString(), any(HttpEntity.class), any(Class.class)))
.thenReturn(new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR));
boolean actual = emailServerInteraction.deleteEmailId(emailAllocation);
assertFalse(actual);
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/TrashEmailApplicationTests.java
================================================
package io.github.trashemail;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@Disabled
@SpringBootTest
class TrashEmailApplicationTests {
@Test
void contextLoads() {
}
}
================================================
FILE: TrashEmailService/src/test/java/io/github/trashemail/TrashEmailResourceTest.java
================================================
package io.github.trashemail;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.trashemail.Configurations.EmailServerConfig;
import io.github.trashemail.Configurations.TrashEmailConfig;
import io.github.trashemail.DTO.ConnectorStats;
import io.github.trashemail.DTO.CreateEmailRequest;
import io.github.trashemail.DTO.DeleteEmailRequest;
import io.github.trashemail.DTO.SendEmailRequest;
import io.github.trashemail.models.EmailAllocation;
import io.github.trashemail.repositories.EmailAllocationRepository;
import io.github.trashemail.repositories.EmailCounterRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.Date;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@AutoConfigureMockMvc
@WebMvcTest(controllers = TrashEmailResource.class)
class TrashEmailResourceTest {
@MockBean
private EmailAllocationRepository emailAllocationRepository;
@MockBean
private EmailCounterRepository emailCounterRepository;
@MockBean
private EmailServerConfig emailServerConfig;
@MockBean
private EmailServerInteraction emailServerInteraction;
@Autowired
private MockMvc mockMvc;
@MockBean
private RestTemplate restTemplate;
@MockBean
private TrashEmailConfig trashEmailConfig;
@Test
void testPresentDashBoard() throws Exception {
ConnectorStats connectorStats = new ConnectorStats();
connectorStats.setConnectorName("connectorname");
when(trashEmailConfig.getVersion()).thenReturn("1.0.0");
when(trashEmailConfig.getConnectorURLs()).thenReturn(Arrays.asList("www.connection.com"));
when(emailServerConfig.getHosts()).thenReturn(Arrays.asList("localhost"));
when(emailAllocationRepository.findByEmailIdEndsWith(anyString())).thenReturn(Arrays.asList(new EmailAllocation()));
when(emailAllocationRepository.getEmailIdsCreatedTodayCount()).thenReturn(1L);
when(emailAllocationRepository.getEmailIdsCreatedInWeek(any(Date.class), any(Date.class))).thenReturn(Arrays.asList(1L));
when(emailAllocationRepository.count()).thenReturn(1L);
when(restTemplate.getForEntity(anyString(), any(Class.class)))
.thenReturn(new ResponseEntity(connectorStats, HttpStatus.OK));
mockMvc.perform(get("/stats"))
.andDo(print())
.andExpect(content().json("{\"numberOfUsers\":null,\"numberOfEmailsRegistered\":null,\"domainsToNumbers\":{\"localhost\":1},\"emailIdsCreatedToday\":1,\"emailIdsCreatedInWeek\":[1],\"version\":\"1.0.0\",\"numberOfEmailsProcessed\":0,\"totalNumberOfUsers\":null,\"connectorStats\":[{\"connectorName\":\"connectorname\",\"activeUsers\":null,\"totalNumberOfUsers\":null,\"activeEmailIds\":null,\"totalNumberOfEmailIds\":null}]}"))
.andExpect(status().isOk());
}
@Test
void testSendEmailTargetNotActive() throws Exception {
doNothing().when(emailCounterRepository).updateCount();
when(emailAllocationRepository.findByEmailIdAndIsActiveTrue(anyString())).thenReturn(null);
SendEmailRequest sendEmailRequest = new SendEmailRequest();
sendEmailRequest.setEmailId("emailid");
String payload = new ObjectMapper().writeValueAsString(sendEmailRequest);
mockMvc.perform(post("/sendMail")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(payload))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("Mail target not active"));
}
@Test
void testSendEmail() throws Exception {
doNothing().when(emailCounterRepository).updateCount();
EmailAllocation emailAllocation = new EmailAllocation();
emailAllocation.setDestinationType("url");
emailAllocation.setDestination("destination");
when(emailAllocationRepository.findByEmailIdAndIsActiveTrue(anyString())).thenReturn(emailAllocation);
SendEmailRequest sendEmailRequest = new SendEmailRequest();
sendEmailRequest.setEmailId("emailid");
String payload = new ObjectMapper().writeValueAsString(sendEmailRequest);
when(restTemplate.postForEntity(anyString(), any(Object.class), any(Class.class)))
.thenReturn(ResponseEntity.ok(""));
mockMvc.perform(post("/sendMail")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(payload))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(""));
}
@Test
void testSendEmailTargetTypeEmail() throws Exception {
doNothing().when(emailCounterRepository).updateCount();
EmailAllocation emailAllocation = new EmailAllocation();
emailAllocation.setDestinationType("email");
emailAllocation.setDestination("destination");
when(emailAllocationRepository.findByEmailIdAndIsActiveTrue(anyString())).thenReturn(emailAllocation);
SendEmailRequest sendEmailRequest = new SendEmailRequest();
sendEmailRequest.setEmailId("emailid");
String payload = new ObjectMapper().writeValueAsString(sendEmailRequest);
when(restTemplate.postForEntity(anyString(), any(Object.class), any(Class.class)))
.thenReturn(ResponseEntity.ok(""));
mockMvc.perform(post("/sendMail")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(payload))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string("Mail Sent."));
}
@Test
void testDeleteEmailIdBadRequest() throws Exception {
DeleteEmailRequest deleteEmailRequest = new DeleteEmailRequest();
deleteEmailRequest.setEmailId("emailId");
String payload = new ObjectMapper().writeValueAsString(deleteEmailRequest);
when(emailAllocationRepository.findByEmailIdAndIsActiveTrue(anyString())).thenReturn(null);
mockMvc.perform(post("/delete")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(payload))
.andDo(print())
.andExpect(status().isBadRequest());
}
@Test
void testDeleteEmailId() throws Exception {
DeleteEmailRequest deleteEmailRequest = new DeleteEmailRequest();
deleteEmailRequest.setEmailId("emailId");
String payload = new ObjectMapper().writeValueAsString(deleteEmailRequest);
EmailAllocation emailAllocation = new EmailAllocation();
when(emailAllocationRepository.findByEmailIdAndIsActiveTrue(anyString())).thenReturn(emailAllocation);
when(emailServerInteraction.deleteEmailId(any(EmailAllocation.class))).thenReturn(true);
when(emailAllocationRepository.save(any(EmailAllocation.class))).thenReturn(emailAllocation);
mockMvc.perform(post("/delete")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(payload))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().json("{\"emailId\":\"emailId\",\"isDeleted\":true}"));
}
@Test
void testCreateEmailBadRequest() throws Exception {
CreateEmailRequest createEmailRequest = new CreateEmailRequest();
createEmailRequest.setEmailId("emailid");
String payload = new ObjectMapper().writeValueAsString(createEmailRequest);
when(emailAllocationRepository.findByEmailIdAndIsActiveTrue(anyString())).thenReturn(new EmailAllocation());
mockMvc.perform(post("/create")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(payload))
.andDo(print())
.andExpect(status().isBadRequest());
}
@Test
void testCreateEmailCreated() throws Exception {
CreateEmailRequest createEmailRequest = new CreateEmailRequest();
createEmailRequest.setEmailId("emailid");
createEmailRequest.setDestination("destination");
createEmailRequest.setDestinationType("destinationtype");
EmailAllocation emailAllocation = new EmailAllocation();
String payload = new ObjectMapper().writeValueAsString(createEmailRequest);
when(emailAllocationRepository.findByEmailIdAndIsActiveTrue(anyString())).thenReturn(null);
when(emailAllocationRepository.findByEmailIdAndDestinationAndDestinationType(anyString(),
anyString(),
anyString())).thenReturn(emailAllocation);
when(emailServerInteraction.createEmailId(any(EmailAllocation.class))).thenReturn("");
when(emailAllocationRepository.save(any(EmailAllocation.class))).thenReturn(emailAllocation);
mockMvc.perform(post("/create")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(payload))
.andDo(print())
.andExpect(status().isCreated());
}
@Test
void testCreateEmailRandom() throws Exception {
CreateEmailRequest createEmailRequest = new CreateEmailRequest();
createEmailRequest.setEmailId("emailid");
createEmailRequest.setDestination("destination");
createEmailRequest.setDestinationType("destinationtype");
EmailAllocation emailAllocation = new EmailAllocation();
String payload = new ObjectMapper().writeValueAsString(createEmailRequest);
when(emailAllocationRepository.findByEmailIdAndIsActiveTrue(anyString())).thenReturn(null);
when(emailAllocationRepository.findByEmailIdAndDestinationAndDestinationType(anyString(),
anyString(),
anyString())).thenReturn(null);
when(emailServerConfig.getTargetAlias()).thenReturn(Arrays.asList("Alias"));
when(emailServerInteraction.createEmailId(any(EmailAllocation.class))).thenReturn("");
when(emailAllocationRepository.save(any(EmailAllocation.class))).thenReturn(emailAllocation);
mockMvc.perform(post("/create")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(payload))
.andDo(print())
.andExpect(status().isCreated());
}
}
================================================
FILE: build-and-run.sh
================================================
#! /bin/bash
environment=${1:-dev}
export SPRING_PROFILES_ACTIVE=$environment
make $environment
docker-compose up
gitextract_x8eo6s08/ ├── .github/ │ └── ISSUE_TEMPLATE/ │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── TrashEmailService/ │ ├── .gitignore │ ├── Dockerfile │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── io/ │ │ └── github/ │ │ └── trashemail/ │ │ ├── Configurations/ │ │ │ ├── EmailServerConfig.java │ │ │ └── TrashEmailConfig.java │ │ ├── DTO/ │ │ │ ├── ConnectorStats.java │ │ │ ├── CreateEmailRequest.java │ │ │ ├── CreateEmailResponse.java │ │ │ ├── DeleteEmailRequest.java │ │ │ ├── DeleteEmailResponse.java │ │ │ ├── Email.java │ │ │ ├── SendEmailRequest.java │ │ │ ├── TelegramConnectorStats.java │ │ │ └── TrashEmailStats.java │ │ ├── EmailServerInteraction.java │ │ ├── Respositories/ │ │ │ ├── FreeUserIdRepository.java │ │ │ └── UsedUserIdRepository.java │ │ ├── TrashEmailApplication.java │ │ ├── TrashEmailResource.java │ │ ├── exceptions/ │ │ │ ├── EmailAliasNotCreatedExecption.java │ │ │ ├── EmailAlreadyExsitExecption.java │ │ │ └── EmailNotFoundExecption.java │ │ ├── models/ │ │ │ ├── EmailAllocation.java │ │ │ ├── EmailCounter.java │ │ │ ├── FreeUserId.java │ │ │ └── UsedUserId.java │ │ └── repositories/ │ │ ├── EmailAllocationRepository.java │ │ └── EmailCounterRepository.java │ └── test/ │ └── java/ │ └── io/ │ └── github/ │ └── trashemail/ │ ├── DTO/ │ │ ├── ConnectorStatsTest.java │ │ ├── CreateEmailRequestTest.java │ │ ├── CreateEmailResponseTest.java │ │ ├── DeleteEmailRequestTest.java │ │ ├── DeleteEmailResponseTest.java │ │ ├── EmailTest.java │ │ ├── SendEmailRequestTest.java │ │ ├── TelegramConnectorStatsTest.java │ │ └── TrashEmailStatsTest.java │ ├── EmailServerInteractionTests.java │ ├── TrashEmailApplicationTests.java │ └── TrashEmailResourceTest.java └── build-and-run.sh
SYMBOL INDEX (111 symbols across 37 files)
FILE: TrashEmailService/src/main/java/io/github/trashemail/Configurations/EmailServerConfig.java
class EmailServerConfig (line 11) | @Configuration
method toString (line 23) | @Override public String toString() {
FILE: TrashEmailService/src/main/java/io/github/trashemail/Configurations/TrashEmailConfig.java
class TrashEmailConfig (line 11) | @Getter
method toString (line 20) | @Override public String toString() {
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/ConnectorStats.java
class ConnectorStats (line 7) | @Getter
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/CreateEmailRequest.java
class CreateEmailRequest (line 7) | @Getter
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/CreateEmailResponse.java
class CreateEmailResponse (line 7) | @Getter
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/DeleteEmailRequest.java
class DeleteEmailRequest (line 7) | @Getter
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/DeleteEmailResponse.java
class DeleteEmailResponse (line 8) | @Getter
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/Email.java
class Email (line 10) | @Getter
method Email (line 21) | public Email(SendEmailRequest sendEmailRequest){
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/SendEmailRequest.java
class SendEmailRequest (line 9) | @Getter
method toString (line 19) | @Override public String toString() {
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/TelegramConnectorStats.java
class TelegramConnectorStats (line 7) | @Getter
FILE: TrashEmailService/src/main/java/io/github/trashemail/DTO/TrashEmailStats.java
class TrashEmailStats (line 10) | @Getter
FILE: TrashEmailService/src/main/java/io/github/trashemail/EmailServerInteraction.java
class EmailServerInteraction (line 17) | @Component("EmailServerInteraction")
method createEmailId (line 29) | public String createEmailId(EmailAllocation emailAllocation)
method deleteEmailId (line 61) | public boolean deleteEmailId(EmailAllocation emailAllocation) {
FILE: TrashEmailService/src/main/java/io/github/trashemail/Respositories/FreeUserIdRepository.java
type FreeUserIdRepository (line 6) | public interface FreeUserIdRepository
method findTopByOrderByIdAsc (line 8) | public FreeUserId findTopByOrderByIdAsc();
FILE: TrashEmailService/src/main/java/io/github/trashemail/Respositories/UsedUserIdRepository.java
type UsedUserIdRepository (line 10) | public interface UsedUserIdRepository
method findByChatIdAndIsActiveTrue (line 12) | public List<UsedUserId> findByChatIdAndIsActiveTrue(long chatId);
method findByUserId (line 13) | public UsedUserId findByUserId(String userId);
method findAllByCreateDateTimeBetween (line 15) | public List<UsedUserId> findAllByCreateDateTimeBetween(
method getUserIdsCreatedBeforeTenMinutes (line 18) | @Query(value = "SELECT * FROM used_user_ids " +
FILE: TrashEmailService/src/main/java/io/github/trashemail/TrashEmailApplication.java
class TrashEmailApplication (line 11) | @SpringBootApplication
method main (line 15) | public static void main(String[] args) {
method restTemplate (line 19) | @Bean
FILE: TrashEmailService/src/main/java/io/github/trashemail/TrashEmailResource.java
class TrashEmailResource (line 26) | @RestController
method createEmailId (line 51) | @PostMapping(value = "/create")
method deleteEmailId (line 93) | @PostMapping(value = "/delete")
method sendMail (line 118) | @PostMapping(value = "/sendMail")
method presentDashBoard (line 154) | @GetMapping(value = "/stats")
FILE: TrashEmailService/src/main/java/io/github/trashemail/exceptions/EmailAliasNotCreatedExecption.java
class EmailAliasNotCreatedExecption (line 3) | public class EmailAliasNotCreatedExecption extends Exception {
method EmailAliasNotCreatedExecption (line 4) | public EmailAliasNotCreatedExecption(String message){
FILE: TrashEmailService/src/main/java/io/github/trashemail/exceptions/EmailAlreadyExsitExecption.java
class EmailAlreadyExsitExecption (line 3) | public class EmailAlreadyExsitExecption extends Exception {
method EmailAlreadyExsitExecption (line 4) | public EmailAlreadyExsitExecption(){
FILE: TrashEmailService/src/main/java/io/github/trashemail/exceptions/EmailNotFoundExecption.java
class EmailNotFoundExecption (line 3) | public class EmailNotFoundExecption extends Exception {
method EmailNotFoundExecption (line 4) | public EmailNotFoundExecption(){
FILE: TrashEmailService/src/main/java/io/github/trashemail/models/EmailAllocation.java
class EmailAllocation (line 12) | @Getter
method EmailAllocation (line 34) | public EmailAllocation(CreateEmailRequest emailRequest){
method toString (line 42) | @Override public String toString() {
FILE: TrashEmailService/src/main/java/io/github/trashemail/models/EmailCounter.java
class EmailCounter (line 12) | @Entity
FILE: TrashEmailService/src/main/java/io/github/trashemail/models/FreeUserId.java
class FreeUserId (line 9) | @Entity
FILE: TrashEmailService/src/main/java/io/github/trashemail/models/UsedUserId.java
class UsedUserId (line 11) | @Entity
FILE: TrashEmailService/src/main/java/io/github/trashemail/repositories/EmailAllocationRepository.java
type EmailAllocationRepository (line 11) | public interface EmailAllocationRepository
method findByEmailIdAndIsActiveTrue (line 13) | EmailAllocation findByEmailIdAndIsActiveTrue(String emailId);
method findByEmailIdAndDestinationAndDestinationType (line 14) | EmailAllocation findByEmailIdAndDestinationAndDestinationType(String e...
method findByEmailIdEndsWith (line 17) | List<EmailAllocation> findByEmailIdEndsWith(String domain);
method getEmailIdsCreatedTodayCount (line 18) | @Query(
method getEmailIdsCreatedInWeek (line 27) | @Query(
FILE: TrashEmailService/src/main/java/io/github/trashemail/repositories/EmailCounterRepository.java
type EmailCounterRepository (line 10) | public interface EmailCounterRepository
method updateCount (line 13) | @Transactional
method count (line 19) | @Query(value = "select ec.count from EmailCounter ec where ec.id=1")
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/ConnectorStatsTest.java
class ConnectorStatsTest (line 8) | public class ConnectorStatsTest {
method setUp (line 11) | @BeforeEach
method gettersNullTest (line 16) | @Test
method settersTest (line 25) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/CreateEmailRequestTest.java
class CreateEmailRequestTest (line 8) | public class CreateEmailRequestTest {
method setUp (line 11) | @BeforeEach
method gettersNullTest (line 16) | @Test
method settersTest (line 25) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/CreateEmailResponseTest.java
class CreateEmailResponseTest (line 8) | public class CreateEmailResponseTest {
method setUp (line 11) | @BeforeEach
method gettersNullTest (line 16) | @Test
method settersTest (line 22) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/DeleteEmailRequestTest.java
class DeleteEmailRequestTest (line 8) | public class DeleteEmailRequestTest {
method setUp (line 11) | @BeforeEach
method getterNullTest (line 16) | @Test
method setterTest (line 21) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/DeleteEmailResponseTest.java
class DeleteEmailResponseTest (line 8) | public class DeleteEmailResponseTest {
method setUp (line 11) | @BeforeEach
method settersTest (line 16) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/EmailTest.java
class EmailTest (line 14) | public class EmailTest {
method setUp (line 18) | @BeforeEach
method constructorTest (line 24) | @Test
method settersTest (line 34) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/SendEmailRequestTest.java
class SendEmailRequestTest (line 11) | public class SendEmailRequestTest {
method setUp (line 14) | @BeforeEach
method gettersNullTest (line 19) | @Test
method settersTest (line 28) | @Test
method toStringTest (line 51) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/TelegramConnectorStatsTest.java
class TelegramConnectorStatsTest (line 8) | public class TelegramConnectorStatsTest {
method setUp (line 11) | @BeforeEach
method gettersNullTest (line 16) | @Test
method settersTest (line 24) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/DTO/TrashEmailStatsTest.java
class TrashEmailStatsTest (line 15) | public class TrashEmailStatsTest {
method setUp (line 18) | @BeforeEach
method gettersNullTest (line 23) | @Test
method settersTest (line 36) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/EmailServerInteractionTests.java
class EmailServerInteractionTests (line 28) | @ExtendWith(MockitoExtension.class)
method setUpBeforeClass (line 40) | @BeforeAll
method setUpBefore (line 48) | @BeforeEach
method teardown (line 55) | @AfterEach
method testCreateEmail (line 62) | @Test
method testCreateEmailException (line 73) | @Test
method testDeleteEmailId (line 83) | @Test
method testDeleteEmailIdBadRequest (line 95) | @Test
method testDeleteEmailIdBadRequestOtherStatusCode (line 107) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/TrashEmailApplicationTests.java
class TrashEmailApplicationTests (line 7) | @Disabled
method contextLoads (line 11) | @Test
FILE: TrashEmailService/src/test/java/io/github/trashemail/TrashEmailResourceTest.java
class TrashEmailResourceTest (line 37) | @AutoConfigureMockMvc
method testPresentDashBoard (line 56) | @Test
method testSendEmailTargetNotActive (line 81) | @Test
method testSendEmail (line 100) | @Test
method testSendEmailTargetTypeEmail (line 127) | @Test
method testDeleteEmailIdBadRequest (line 154) | @Test
method testDeleteEmailId (line 169) | @Test
method testCreateEmailBadRequest (line 189) | @Test
method testCreateEmailCreated (line 203) | @Test
method testCreateEmailRandom (line 226) | @Test
Condensed preview — 48 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (92K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 834,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 595,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
},
{
"path": ".gitignore",
"chars": 717,
"preview": "HELP.md\ntarget/\nmvnw\nmvnw.cmd\n**/.mvn/wrapper/**\n### Ignore vim swp files\n*.swp\n### Ignore application-<enc>.yml propert"
},
{
"path": ".gitmodules",
"chars": 287,
"preview": "[submodule \"TrashEmailFetchMail\"]\n\tpath = TrashEmailFetchMail\n\turl = https://github.com/TrashEmail/TrashEmailFetchMail.g"
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Makefile",
"chars": 1542,
"preview": "##################################################################\n# Project Convenience Makefile Wrapper for Maven &"
},
{
"path": "README.md",
"chars": 10787,
"preview": "<p align=center>\n\t<img src=\"./TrashEmail.png\">\n</p>\n\n[. The extraction includes 48 files (81.7 KB), approximately 19.8k tokens, and a symbol index with 111 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.