Skip to content

Commit c244438

Browse files
author
Josh Lospinoso
committed
Version 0.2.0
1 parent 1b88e10 commit c244438

35 files changed

+781
-43
lines changed

Diff for: build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
apply plugin:'java'
22
apply plugin:'groovy'
33

4-
version = '0.1.0'
5-
description = 'MMS batch service'
4+
version = '0.2.0'
5+
description = 'A multimedia message and email batch service'
66

77
task wrapper(type: Wrapper) {
88
gradleVersion = '2.6'

Diff for: config.json

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"subscribers": [
44
"5551234567"
55
],
6+
"emailSubscribers": [
7+
"dailyc@lospi.net"
8+
],
69
"messages": [
710
"Hello world!",
811
"Foo!"

Diff for: dailyc-core/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ repositories {
1919

2020
dependencies {
2121
compile project(':mogreet')
22+
compile project(':dailyc-mail')
2223
compile ('org.springframework.boot:spring-boot-starter-actuator',
2324
'org.codehaus.groovy:groovy-all:2.4.+',
2425
'org.springframework:spring-context:4.+',

Diff for: dailyc-core/src/main/groovy/net/lospi/dailyc/DailycConfiguration.groovy

+37-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ package net.lospi.dailyc
22

33
import groovy.json.JsonSlurper
44
import groovy.util.logging.Slf4j
5+
import net.lospi.dailyc.comm.MailSender
56
import net.lospi.dailyc.comm.MogreetSender
67
import net.lospi.dailyc.comm.MogreetSubscriber
78
import net.lospi.dailyc.comm.MogreetUploader
89
import net.lospi.dailyc.persistence.BatchLoader
910
import net.lospi.dailyc.persistence.Dao
1011
import net.lospi.dailyc.util.Hasher
12+
import net.lospi.mail.core.EmailSendResponseFactory
13+
import net.lospi.mail.MailManager
14+
import net.lospi.mail.multipart.JpegDataSourceFactory
15+
import net.lospi.mail.multipart.MultipartMailFactory
1116
import net.lospi.mogreet.MogreetManager
1217
import net.lospi.mogreet.core.AuthorizationToken
1318
import net.lospi.mogreet.core.BaseResponse
@@ -55,11 +60,27 @@ class DailycConfiguration {
5560
private String databaseUsername
5661
@Value('${database.password}')
5762
private String databasePassword
63+
@Value('${email.userName}')
64+
private String emailUserName
65+
@Value('${email.password}')
66+
private String emailPassword
67+
@Value('${email.hostName}')
68+
private String emailHostName
69+
@Value('${email.sslSmtpPort}')
70+
private String sslSmtpPort
71+
@Value('${email.attachmentName}')
72+
private String emailAttachmentName
73+
@Value('${email.fromName}')
74+
private String emailFromName
75+
@Value('${email.toName}')
76+
private String emailToName
77+
@Value('${email.from}')
78+
private String emailFrom
5879

5980
@Bean
6081
public DataSource dataSource() {
61-
new DriverManagerDataSource( driverClassName:databaseDriver, url:databaseUrl, username:databaseUsername,
62-
password:databasePassword )
82+
new DriverManagerDataSource(driverClassName:databaseDriver, url:databaseUrl, username:databaseUsername,
83+
password:databasePassword)
6384
}
6485

6586
@Bean
@@ -88,6 +109,16 @@ class DailycConfiguration {
88109
getRequestEncoder, postRequestEncoder)
89110
}
90111

112+
@Bean
113+
public MailManager mailManager() {
114+
MultipartMailFactory multipartMailFactory = new MultipartMailFactory()
115+
EmailSendResponseFactory emailSendResponseFactory = new EmailSendResponseFactory()
116+
JpegDataSourceFactory jpegDataSourceFactory = new JpegDataSourceFactory()
117+
return new MailManager(emailUserName, emailPassword, emailHostName, sslSmtpPort,
118+
emailAttachmentName, emailFromName,
119+
emailToName, multipartMailFactory, emailSendResponseFactory, jpegDataSourceFactory)
120+
}
121+
91122
@Bean
92123
DailycManager dailycBatch() {
93124
File configFile = new File(configPath)
@@ -99,8 +130,11 @@ class DailycConfiguration {
99130
MogreetSender sender = new MogreetSender(manager: manager, campaignId: campaignId, from: from)
100131
MogreetSubscriber subscriber = new MogreetSubscriber(manager: manager, campaignId: campaignId)
101132
MogreetUploader mogreetUploader = new MogreetUploader(manager: manager)
133+
MailManager mailManager = mailManager()
134+
MailSender mailSender = new MailSender(from: emailFrom, mailManager: mailManager)
102135
new DailycManager(mogreetSender: sender, mogreetSubscriber: subscriber,
103-
mogreetUploader: mogreetUploader, dao: dao, batchLoader: batchLoader)
136+
mogreetUploader: mogreetUploader, dao: dao,
137+
batchLoader: batchLoader, mailSender: mailSender)
104138
}
105139

106140
private AuthorizationToken makeToken() throws IOException {

Diff for: dailyc-core/src/main/groovy/net/lospi/dailyc/DailycManager.groovy

+52-17
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
package net.lospi.dailyc
22

33
import groovy.util.logging.Slf4j
4+
import net.lospi.dailyc.comm.MailSender
45
import net.lospi.dailyc.comm.MogreetSender
56
import net.lospi.dailyc.comm.MogreetSubscriber
67
import net.lospi.dailyc.comm.MogreetUploader
8+
import net.lospi.dailyc.core.EmailSubscriber
79
import net.lospi.dailyc.core.ImageFile
810
import net.lospi.dailyc.core.MessageBody
911
import net.lospi.dailyc.core.Subscriber
1012
import net.lospi.dailyc.persistence.BatchLoader
1113
import net.lospi.dailyc.persistence.Dao
14+
import net.lospi.mail.MailManager
1215
import net.lospi.mogreet.core.UploadResponse
1316

1417
@Slf4j
1518
class DailycManager implements Runnable {
19+
MailSender mailSender
1620
MogreetSender mogreetSender
1721
MogreetSubscriber mogreetSubscriber
1822
MogreetUploader mogreetUploader
@@ -30,39 +34,48 @@ class DailycManager implements Runnable {
3034
log.info("[+] Loaded {} messages from disk", messages.size())
3135
def nMessages = dao.loadMessages(messages).size()
3236
log.info("[+] {} messages updated", nMessages)
33-
log.debug("[ ] Updating subscribers")
37+
log.debug("[ ] Updating MMS subscribers")
3438
def subscribers = batchLoader.subscribers
35-
log.info("[+] Loaded {} subscribers from disk", subscribers.size())
39+
log.info("[+] Loaded {} MMS subscribers from disk", subscribers.size())
3640
def nSubscribers = dao.loadSubscribers(subscribers).size()
37-
log.info("[+] {} subscribers updated", nSubscribers)
41+
log.info("[+] {} MMS subscribers updated", nSubscribers)
42+
log.debug("[ ] Updating email subscribers")
43+
def emailSubscribers = batchLoader.emailSubscribers
44+
log.info("[+] Loaded {} email subscribers from disk", emailSubscribers.size())
45+
def nEmailSubscribers = dao.loadEmailSubscribers(emailSubscribers).size()
46+
log.info("[+] {} email subscribers updated", nEmailSubscribers)
3847
def nextMessage = dao.nextMessageBody()
3948
def nextImage = dao.nextImageFile()
4049
log.info("[ ] Next message: {}", nextMessage.contents)
4150
log.info("[ ] Next image: {}", nextImage.name)
4251
if(nextMessage.lastUse)
4352
log.warn("[-] Next message has been used previously: {}", nextMessage.lastUse)
4453
if(nextImage.lastUse)
45-
log.warn("[-] Previous message has been used previously: {}", nextImage.lastUse)
54+
log.warn("[-] Next image has been used previously: {}", nextImage.lastUse)
4655
}
4756

4857
void run() {
4958
def selectedFile = dao.nextImageFile()
5059
def selectedMessage = dao.nextMessageBody()
5160
def subscribers = dao.getSubscribers()
61+
def emailSubscribers = dao.getEmailSubscribers()
5262

53-
validateInput(selectedMessage, selectedFile, subscribers)
63+
validateInput(selectedMessage, selectedFile, subscribers, emailSubscribers)
5464
String contentId = uploadContent(selectedFile)
55-
int messagesSuccessful = sendMessages(subscribers, selectedMessage, selectedFile, contentId)
56-
reportOnBatchSuccess(messagesSuccessful, subscribers)
65+
int mmsSuccessful = sendMms(subscribers, selectedMessage, selectedFile, contentId)
66+
int emailSuccessful = sendEmail(emailSubscribers, selectedMessage, selectedFile)
67+
reportOnBatchSuccess(mmsSuccessful, emailSuccessful, subscribers, emailSubscribers)
5768
}
5869

59-
private void reportOnBatchSuccess(int messagesSuccessful, List<Subscriber> numbers) {
60-
if (messagesSuccessful == numbers.size()) {
70+
private void reportOnBatchSuccess(int mmsSuccessful, int emailSuccessful,
71+
List<Subscriber> numbers, List<EmailSubscriber> emails) {
72+
def numberRequested = numbers.size() + emails.size()
73+
def numberSuccessful = mmsSuccessful + emailSuccessful;
74+
if (numberRequested == numberSuccessful) {
6175
log.info("[+] Batch completed with all messages sent successfully.")
6276
} else {
63-
def numberFailed = numbers.size() - messagesSuccessful
64-
log.error("[-] Batch completed with {} of {} messages sent successfully.", messagesSuccessful, numbers.size())
65-
throw new RuntimeException(String.format("%d messages failed to send", numberFailed))
77+
log.error("[-] Batch completed with {} of {} messages sent successfully.", numberSuccessful, numberRequested)
78+
throw new RuntimeException(String.format("%d messages failed to send", numberRequested - numberSuccessful))
6679
}
6780
}
6881

@@ -84,19 +97,22 @@ class DailycManager implements Runnable {
8497
contentId
8598
}
8699

87-
private void validateInput(selectedMessage, selectedFile, numbers) {
100+
private void validateInput(selectedMessage, selectedFile, numbers, emails) {
88101
if (!selectedMessage)
89102
throw new RuntimeException("MessageBodyGenerator returned null message.")
90103
if (!selectedFile)
91104
throw new RuntimeException("ImageFileGenerator returned null ImageFile.")
92105
if (numbers.size() == 0)
93106
throw new RuntimeException("SubscriberGenerator returned no numbers.")
107+
if (emails.size() == 0)
108+
throw new RuntimeException("EmailSubscriberGenerator returned no numbers.")
94109
log.info("[+] Selected message: \"{}\"", selectedMessage)
95110
log.info("[+] Selected file: {}", selectedFile)
96-
log.info("[+] {} subscribers.", numbers.size())
111+
log.info("[+] {} MMS subscribers.", numbers.size())
112+
log.info("[+] {} email subscribers.", numbers.size())
97113
}
98114

99-
private int sendMessages(List<Subscriber> subscribers, MessageBody messageBody, ImageFile imageFile,
115+
private int sendMms(List<Subscriber> subscribers, MessageBody messageBody, ImageFile imageFile,
100116
String contentId) {
101117
return subscribers.count{ subscriber ->
102118
try {
@@ -107,11 +123,30 @@ class DailycManager implements Runnable {
107123
def mms = dao.createSentMms(subscriber, messageBody, imageFile, date)
108124
log.info("[+] Sent MMS \n{}", mms)
109125
} else {
110-
log.error("[-] Not sent to {}:\n{}\n{}", subscriber, subscribeResponse, sendResponse)
126+
log.error("[-] MMS not sent to {}:\n{}\n{}", subscriber, subscribeResponse, sendResponse)
111127
}
112128
return sendResponse.successful
113129
} catch (any) {
114-
log.error("[-] Could not subscribe/send to {}:\n", subscriber, any.toString())
130+
log.error("[-] Could not subscribe/send to {}: {}\n", subscriber, any.toString())
131+
return false
132+
}
133+
}
134+
}
135+
136+
private int sendEmail(List<EmailSubscriber> emailSubscribers, MessageBody messageBody, ImageFile imageFile) {
137+
return emailSubscribers.count{ subscriber ->
138+
try {
139+
def sendResponse = mailSender.send(subscriber, messageBody, imageFile)
140+
if (sendResponse.successful) {
141+
Date date = new Date()
142+
def email = dao.createSentEmail(subscriber, messageBody, imageFile, date)
143+
log.info("[+] Sent email \n{}", email)
144+
} else {
145+
log.error("[-] Email not sent to {}:\n{}", subscriber, sendResponse)
146+
}
147+
return sendResponse.successful
148+
} catch (any) {
149+
log.error("[-] Could not send to {}: {}\n", subscriber, any.toString())
115150
return false
116151
}
117152
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package net.lospi.dailyc.comm
2+
3+
import groovy.util.logging.Slf4j
4+
import net.lospi.dailyc.core.EmailSubscriber
5+
import net.lospi.dailyc.core.ImageFile
6+
import net.lospi.dailyc.core.MessageBody
7+
import net.lospi.mail.MailManager
8+
import net.lospi.mail.core.EmailSendRequest
9+
10+
@Slf4j
11+
class MailSender {
12+
MailManager mailManager
13+
String from
14+
15+
def send(EmailSubscriber emailSubscriber, MessageBody messageBody, ImageFile imageFile) {
16+
log.info("[ ] Sending image {} to email {}; message: {}", imageFile, emailSubscriber, messageBody)
17+
def request = new EmailSendRequest(emailSubscriber.address, from, messageBody.contents, imageFile.image)
18+
def result = mailManager.send(request)
19+
if(result.successful)
20+
log.info("[+] Success! Response from mail server: {}", result.messageResponse)
21+
else
22+
log.error("[-] Failure! Response from mail server: %n{}", result.messageResponse)
23+
return result
24+
}
25+
}

Diff for: dailyc-core/src/main/groovy/net/lospi/dailyc/comm/MogreetSender.groovy

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package net.lospi.dailyc.comm
22

33
import groovy.util.logging.Slf4j
4+
import net.lospi.dailyc.core.EmailSubscriber
45
import net.lospi.dailyc.core.MessageBody
56
import net.lospi.dailyc.core.Subscriber
67
import net.lospi.mogreet.MogreetManager
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package net.lospi.dailyc.core
2+
3+
import grails.persistence.Entity
4+
5+
@Entity
6+
class EmailSubscriber {
7+
String address
8+
Date lastUse
9+
10+
static hasMany = [
11+
sentEmail : SentEmail
12+
]
13+
14+
static constraints = {
15+
lastUse(nullable: true)
16+
}
17+
18+
@Override
19+
public String toString() {
20+
return """\
21+
EmailSubscriber{
22+
id=$id,
23+
address='$address',
24+
lastUse=$lastUse,
25+
version=$version
26+
}"""
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package net.lospi.dailyc.core
2+
3+
class NoEmailSubscribersException {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.lospi.dailyc.core
2+
3+
import grails.persistence.Entity
4+
5+
@Entity
6+
class SentEmail {
7+
EmailSubscriber emailSubscriber
8+
MessageBody messageBody
9+
ImageFile imageFile
10+
Date sentDate
11+
12+
@Override
13+
public String toString() {
14+
final StringBuilder sb = new StringBuilder("SentEmail{");
15+
sb.append("emailSubscriber=").append(emailSubscriber);
16+
sb.append(", messageBody=").append(messageBody);
17+
sb.append(", imageFile=").append(imageFile);
18+
sb.append(", sentDate=").append(sentDate);
19+
sb.append('}');
20+
return sb.toString();
21+
}
22+
}

Diff for: dailyc-core/src/main/groovy/net/lospi/dailyc/persistence/BatchLoader.groovy

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class BatchLoader {
2020
(List<String>) getKey("subscribers")
2121
}
2222

23+
List<String> getEmailSubscribers() {
24+
(List<String>) getKey("emailSubscribers")
25+
}
26+
2327
private File getKeyFile(String key) {
2428
String path = getKey(key)
2529
File file = new File(path)

Diff for: dailyc-core/src/main/groovy/net/lospi/dailyc/persistence/Dao.groovy

+23
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import net.lospi.dailyc.util.Hasher
88
class Dao {
99
Hasher hasher
1010

11+
List<EmailSubscriber> loadEmailSubscribers(List<String> emailSubscribers) {
12+
emailSubscribers.collect{EmailSubscriber.findOrSaveByAddress(it)}
13+
}
14+
1115
List<Subscriber> loadSubscribers(List<String> subscribers) {
1216
subscribers.collect{Subscriber.findOrSaveByNumber(it)}
1317
}
@@ -49,6 +53,13 @@ class Dao {
4953
subscribers
5054
}
5155

56+
List<Subscriber> getEmailSubscribers() {
57+
def emailSubscribers = EmailSubscriber.getAll()
58+
if(emailSubscribers.size() == 0)
59+
throw new NoSubscribersException()
60+
emailSubscribers
61+
}
62+
5263
SentMms createSentMms(Subscriber subscriber, MessageBody messageBody, ImageFile imageFile, Date sentDate) {
5364
SentMms sentMms = new SentMms(subscriber: subscriber, messageBody: messageBody, imageFile: imageFile,
5465
sentDate: sentDate)
@@ -60,4 +71,16 @@ class Dao {
6071
imageFile.save()
6172
sentMms.save()
6273
}
74+
75+
SentEmail createSentEmail(EmailSubscriber emailSubscriber, MessageBody messageBody, ImageFile imageFile, Date sentDate) {
76+
SentEmail sentMms = new SentEmail(emailSubscriber: emailSubscriber, messageBody: messageBody, imageFile: imageFile,
77+
sentDate: sentDate)
78+
emailSubscriber.lastUse = sentDate
79+
messageBody.lastUse = sentDate
80+
imageFile.lastUse = sentDate
81+
emailSubscriber.save()
82+
messageBody.save()
83+
imageFile.save()
84+
sentMms.save()
85+
}
6386
}

0 commit comments

Comments
 (0)