Skip to content

Commit

Permalink
feat(split) Automatically split SMS in parts according to encoding
Browse files Browse the repository at this point in the history
- Automatically guess encoder that can encode properly the message
- Split according to encoder (either 160/153 characters for GSM 7-bit, 140/134 characters for GSM 8-bit or 70/67 characters for UCS-2)
- fixes #69
- Support TLV message_payload optional parameter (#88)
- Add service configurer dedicated to SMSGlobal
- Need to add different configuration phases in order to be able to override some values for a particular service provider (like SMSGlobal)
  • Loading branch information
aurelien-baudet committed Dec 21, 2019
1 parent d6f4c2f commit c06f80e
Show file tree
Hide file tree
Showing 148 changed files with 12,239 additions and 646 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ target/
.idea/
src/docs/asciidoc/*.png
.attach_pid*
.sts4-cache/
56 changes: 30 additions & 26 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1435,7 +1435,7 @@ public class EmailPropertiesTest
.content("string body"));
assertThat(greenMail).receivedMessages()
.count(is(6))
.forEach()
.every()
.subject(is("Simple"))
.body()
.contentAsString(is("string body"))
Expand Down Expand Up @@ -1780,7 +1780,7 @@ The construction of the SMS is done using a fluent API in order to chain calls a
Properties are directly provided in the code. You can instead <<properties-handling,use a configuration file>>.

[[sms-template]]
==== use a template for SMS content
==== Use a template for SMS content


This sample shows how to send a SMS with a content following a template engine language.
Expand Down Expand Up @@ -1978,41 +1978,45 @@ public class BasicSmsglobalSmppSample
// in System properties)
Properties properties = new Properties();
properties.setProperty("ogham.sms.smpp.host", "smsglobal.com"); // <1>
properties.setProperty("ogham.sms.smpp.port", "1775"); // <2>
properties.setProperty("ogham.sms.smpp.system-id", "<your smsglobal username available in API keys>"); // <3>
properties.setProperty("ogham.sms.smpp.password", "<your smsglobal password available in API keys>"); // <4>
properties.setProperty("ogham.sms.from", "<phone number to display for the sender>"); // <5>
properties.setProperty("ogham.sms.smpp.system-id", "<your smsglobal username available in API keys>"); // <2>
properties.setProperty("ogham.sms.smpp.password", "<your smsglobal password available in API keys>"); // <3>
properties.setProperty("ogham.sms.from", "<phone number to display for the sender>"); // <4>
// Instantiate the messaging service using default behavior and
// provided properties
MessagingService service = MessagingBuilder.standard() // <6>
MessagingService service = MessagingBuilder.standard() // <5>
.environment()
.properties(properties) // <7>
.properties(properties) // <6>
.and()
.build(); // <8>
.build(); // <7>
// send the sms using fluent API
service.send(new Sms() // <9>
.content("sms content")
.to("+33752962193"));
service.send(new Sms() // <8>
.content("abcdefghijklmnopqrstuvwxyz0123456789 @£$¥\nØø\rΔ_ΦΓΛΩΠΨΣΘΞÆæß!\"#¤%&'()*+,-./:;<=>?¡¿§ èéùìòÇÅåÉÄÖÑÜäöñüàsms content with a very very very loooooooooooooooooooonnnnnnnnnnnnnnnnng message that is over 160 characters in order to test the behavior of the sender when message has to be split")
.to("+262693493696"));
}
----
<1> The SmsGlobal server host
<2> The SmsGlobal server port
<3> Your SmsGlobal username
<4> Your SmsGlobal password
<5> The sender phone number
<6> Use the standard builder to configure and instantiate the MessagingService as usual
<7> Provide configuration properties to Ogham as usual
<8> Instantiate the service as usual
<9> Send the SMS as usual
<2> Your SmsGlobal username
<3> Your SmsGlobal password
<4> The sender phone number
<5> Use the standard builder to configure and instantiate the MessagingService as usual
<6> Provide configuration properties to Ogham as usual
<7> Instantiate the service as usual
<8> Send the SMS as usual
https://github.com/groupe-sii/ogham/tree/v2.0.0/sample-standard-usage/src/main/java/fr/sii/ogham/sample/standard/sms/smsglobal/BasicSmsglobalSmppSample.java?ts=4[Source code of the sample].
[role=tab-container-end]
_____


[TIP]
====
You can notice that SMPP server port is not provided. This is because Ogham provides <<service-providers,predefined configuration for well-known service providers>> like https://www.smsglobal.com/[SmsGlobal].
====

==== Sending SMS through OVH


Expand Down Expand Up @@ -3851,7 +3855,7 @@ public class SeveralRecipientsTestSample
.bcc("recipient6@sii.fr"));
assertThat(greenMail).receivedMessages()
.count(is(6)) // <1>
.forEach() // <2>
.every() // <2>
.subject(is("Simple"))
.from()
.address(hasItems("test.sender@sii.fr"))
Expand Down Expand Up @@ -3960,7 +3964,7 @@ public class SeveralEmailsTestSample
.to("recipient3@sii.fr"));
assertThat(greenMail).receivedMessages()
.count(is(3))
.forEach() // <1>
.every() // <1>
.subject(is("Simple"))
.from()
.address(hasItems("test.sender@sii.fr"))
Expand Down Expand Up @@ -4256,23 +4260,23 @@ public class LongSmsTestSample
@Test
public void longMessage() throws MessagingException, IOException
public void longMessageUsingGsm8bit() throws MessagingException, IOException
// @formatter:off
oghamService.send(new Sms()
.content("sms content with a very very very loooooooooo"
+ "oooooooooonnnnnnnnnnnnnnnnng message that is"
+ " over 160 characters in order to test the be"
+ " over 140 characters in order to test the be"
+ "havior of the sender when message has to be split")
.to("0601020304"));
assertThat(smppServer).receivedMessages()
.count(is(2)) // <1>
.message(0) // <2>
.content(is("sms content with a very very very looooooooooooooooooo" // <3>
+ "onnnnnnnnnnnnnnnnng message that is over 160 characters "
+ "onnnnnnnnnnnnnnnnng message that is over 140 characters "
+ "in order to test the beh")).and()
.message(1) // <4>
.content(is("avior of the sender when message has to be split")).and() // <5>
.forEach() // <6>
.every() // <6>
.from()
.number(is("+33603040506")) // <7>
.and()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void simple() throws MessagingException, javax.mail.MessagingException {
.content("string body"));
assertThat(greenMail).receivedMessages()
.count(is(6))
.forEach()
.every()
.subject(is("Simple"))
.body()
.contentAsString(is("string body"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.junit.Test;

import fr.sii.ogham.core.builder.MessagingBuilder;
import fr.sii.ogham.core.builder.configurer.ConfigurationPhase;
import fr.sii.ogham.core.exception.handler.ContentTranslatorException;
import fr.sii.ogham.core.message.content.Content;
import fr.sii.ogham.core.message.content.StringContent;
Expand All @@ -37,7 +38,9 @@ public class JsoupInlineCssTranslatorTest {

@Before
public void setUp() {
ResourceResolver resourceResolver = MessagingBuilder.standard()
MessagingBuilder builder = MessagingBuilder.standard();
builder.configure(ConfigurationPhase.BEFORE_BUILD);
ResourceResolver resourceResolver = builder
.email()
.template(ThymeleafV3EmailBuilder.class)
.classpath()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.mockito.junit.MockitoJUnitRunner;

import fr.sii.ogham.core.builder.MessagingBuilder;
import fr.sii.ogham.core.builder.configurer.ConfigurationPhase;
import fr.sii.ogham.core.exception.handler.ContentTranslatorException;
import fr.sii.ogham.core.id.generator.IdGenerator;
import fr.sii.ogham.core.message.content.Content;
Expand Down Expand Up @@ -65,7 +66,9 @@ public void setUp() {
Mockito.when(generator.generate("left.gif")).thenReturn("left.gif");
Mockito.when(generator.generate("right.gif")).thenReturn("right.gif");
Mockito.when(generator.generate("tw.gif")).thenReturn("tw.gif");
ResourceResolver resourceResolver = MessagingBuilder.standard()
MessagingBuilder builder = MessagingBuilder.standard();
builder.configure(ConfigurationPhase.BEFORE_BUILD);
ResourceResolver resourceResolver = builder
.email()
.template(ThymeleafV3EmailBuilder.class)
.classpath()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
package fr.sii.ogham.it.sms;

import static fr.sii.ogham.assertion.OghamAssertions.assertThat;
import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.is;

import java.io.IOException;
import java.util.Properties;

import org.jsmpp.bean.NumberingPlanIndicator;
import org.jsmpp.InvalidResponseException;
import org.jsmpp.PDUException;
import org.jsmpp.bean.SubmitSm;
import org.jsmpp.bean.TypeOfNumber;
import org.junit.Assert;
import org.jsmpp.extra.NegativeResponseException;
import org.jsmpp.extra.ResponseTimeoutException;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;

import fr.sii.ogham.core.builder.MessagingBuilder;
import fr.sii.ogham.core.exception.MessagingException;
import fr.sii.ogham.core.message.content.TemplateContent;
import fr.sii.ogham.core.service.MessagingService;
import fr.sii.ogham.helper.sms.bean.Alphabet;
import fr.sii.ogham.helper.sms.bean.NumberingPlanIndicator;
import fr.sii.ogham.helper.sms.bean.TypeOfNumber;
import fr.sii.ogham.helper.sms.rule.JsmppServerRule;
import fr.sii.ogham.helper.sms.rule.SmppServerRule;
import fr.sii.ogham.junit.LoggingTestRule;
Expand All @@ -39,17 +42,17 @@ public class SmsSMPPDefaultsTest {
public final SmppServerRule<SubmitSm> smppServer = new JsmppServerRule();

@Before
public void setUp() throws IOException {
Properties additionalProps = new Properties();
additionalProps.setProperty("ogham.sms.smpp.host", "127.0.0.1");
additionalProps.setProperty("ogham.sms.smpp.port", String.valueOf(smppServer.getPort()));
public void setUp() throws IOException, IllegalArgumentException, PDUException, ResponseTimeoutException, InvalidResponseException, NegativeResponseException {
oghamService = MessagingBuilder.standard()
.environment()
.properties("/application.properties")
.properties(additionalProps)
.properties()
.set("ogham.sms.smpp.host", "127.0.0.1")
.set("ogham.sms.smpp.port", smppServer.getPort())
.and()
.and()
.build();
}
}

@Test
public void simple() throws MessagingException, IOException {
Expand All @@ -76,15 +79,15 @@ public void simple() throws MessagingException, IOException {
public void longMessage() throws MessagingException, IOException {
// @formatter:off
oghamService.send(new Sms()
.content("sms content with a very very very loooooooooooooooooooonnnnnnnnnnnnnnnnng message that is over 160 characters in order to test the behavior of the sender when message has to be split")
.content("sms content with a very very very loooooooooooooooooooonnnnnnnnnnnnnnnnng message that is over 140 characters in order to test the behavior of the sender when message has to be split")
.to(NATIONAL_PHONE_NUMBER));
assertThat(smppServer).receivedMessages()
.count(is(2))
.message(0)
.content(is("sms content with a very very very loooooooooooooooooooonnnnnnnnnnnnnnnnng message that is over 160 characters in order to test the beh")).and()
.content(is("sms content with a very very very loooooooooooooooooooonnnnnnnnnnnnnnnnng message that is over 140 characters in order to test the beh")).and()
.message(1)
.content(is("avior of the sender when message has to be split")).and()
.forEach()
.every()
.from()
.number(is(INTERNATIONAL_PHONE_NUMBER))
.typeOfNumber(is(TypeOfNumber.INTERNATIONAL))
Expand Down Expand Up @@ -125,7 +128,7 @@ public void severalRecipients() throws MessagingException, IOException {
.to(NATIONAL_PHONE_NUMBER, "0102030405", "0605040302"));
assertThat(smppServer).receivedMessages()
.count(is(3))
.forEach()
.every()
.content(is("sms content"))
.from()
.number(is(INTERNATIONAL_PHONE_NUMBER))
Expand All @@ -147,16 +150,64 @@ public void severalRecipients() throws MessagingException, IOException {
}

@Test
@Ignore("Not yet implemented")
public void charsets() throws MessagingException, IOException {
// TODO: test several charsets
Assert.fail("not implemented");
public void gsm8bitDefaultAlphabet() throws MessagingException, IOException {
// @formatter:off
oghamService.send(new Sms()
.content("abcdefghijklmnopqrstuvwxyz0123456789 @£$¥\nØø\rΔ_ΦΓΛΩΠΨΣΘΞÆæß!\"#¤%&'()*+,-./:;<=>?¡¿§ èéùìòÇÅåÉÄÖÑÜäöñüà")
.from("0203040506")
.to("+33605040302"));
assertThat(smppServer)
.receivedMessages()
.count(is(1))
.message(0)
.content(is("abcdefghijklmnopqrstuvwxyz0123456789 @£$¥\nØø\rΔ_ΦΓΛΩΠΨΣΘΞÆæß!\"#¤%&'()*+,-./:;<=>?¡¿§ èéùìòÇÅåÉÄÖÑÜäöñüà"))
.rawRequest()
.alphabet(is(Alphabet.ALPHA_8_BIT))
.shortMessage()
.payload(arrayWithSize(102));
// @formatter:on
}

/**
* Each character present in the GSM 8-bit extension table is encoded on two characters: [ESC, char].
*/
@Test
@SuppressWarnings("javadoc")
public void gsm8bitBasicCharacterSetExtension() throws MessagingException, IOException {
// @formatter:off
oghamService.send(new Sms()
.content("|^€{}[~]\\")
.from("0203040506")
.to("+33605040302"));
assertThat(smppServer)
.receivedMessages()
.count(is(1))
.message(0)
.content(is("|^€{}[~]\\"))
.rawRequest()
.alphabet(is(Alphabet.ALPHA_8_BIT))
.shortMessage()
.payload(arrayWithSize(18));
// @formatter:on
}

@Test
@Ignore("Not yet implemented")
public void unicode() throws MessagingException, IOException {
// TODO: test unicode characters
Assert.fail("not implemented");
public void gsmUcs2() throws MessagingException, IOException {
// @formatter:off
oghamService.send(new Sms()
.content("êtes à l'évènement çà et là où vôtre jeûne île hôpital €")
.from("0203040506")
.to("+33605040302"));
assertThat(smppServer)
.receivedMessages()
.count(is(1))
.message(0)
.content(is("êtes à l'évènement çà et là où vôtre jeûne île hôpital €"))
.rawRequest()
.alphabet(is(Alphabet.ALPHA_UCS2))
.shortMessage()
.payload(arrayWithSize(112));
// @formatter:on
}

}
Loading

0 comments on commit c06f80e

Please sign in to comment.