Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Communication]: SMS 1:N Messages, Custom Tags, and Idempotence #16836

Merged
merged 28 commits into from
Mar 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1596b03
Updated SMS clients with new swagger
lsundaralingam Feb 10, 2021
214605a
Updated SMS client tests
lsundaralingam Feb 10, 2021
ea773b2
Updated SMS samples
lsundaralingam Feb 10, 2021
57cc156
Added resending failed messages to SMS samples
lsundaralingam Feb 10, 2021
ba3c2af
Updated SMS clients to latest swagger
lsundaralingam Feb 19, 2021
850d194
Updated SMS client tests and recordings
lsundaralingam Feb 19, 2021
b2b87f6
Updated SMS samples with changes from new swagger
lsundaralingam Feb 19, 2021
527ac62
Added more test cases
lsundaralingam Feb 19, 2021
0c6cad9
Rebased README file
lsundaralingam Feb 20, 2021
52eb222
Fixed pylint issues
lsundaralingam Feb 20, 2021
cfdd168
Added Idempotence Parameters
lsundaralingam Feb 22, 2021
b2a6d6f
Updated SWAGGER formatting
lsundaralingam Feb 23, 2021
34eb926
Added custom SendMessageRequest model to rename the smsSendOptions fi…
lsundaralingam Feb 23, 2021
6576d90
Updated SMS options parameter
lsundaralingam Feb 23, 2021
9590bb7
Hide repeatability_result from SmsSendResult
lsundaralingam Feb 24, 2021
87a2301
Updated failure message in SMS samples
lsundaralingam Feb 24, 2021
1577572
Updated formatting in models file
lsundaralingam Feb 24, 2021
3383cd8
Updated SmsSendResult
lsundaralingam Feb 24, 2021
b64d567
Refactored SmsSendResult
lsundaralingam Feb 24, 2021
63e9dac
Fixed pylint issue
lsundaralingam Feb 24, 2021
521ef56
Updated CHANGELOG
lsundaralingam Feb 26, 2021
51b6396
Use UTC time zone for repeatability_first_sent
lsundaralingam Feb 26, 2021
763fe6c
Cleaned up CHANGELOG
lsundaralingam Feb 27, 2021
c763cdc
Updated SMS samples
lsundaralingam Feb 27, 2021
9c1a87e
Updated SmsSendOptions
lsundaralingam Feb 27, 2021
b486623
Add test for idempotency
lsundaralingam Feb 27, 2021
494827a
Added case when single recipient phone number is a string
lsundaralingam Mar 1, 2021
837fb30
Updated method documentation in SMS clients
lsundaralingam Mar 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions sdk/communication/azure-communication-sms/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Release History

## 1.0.0b6 (Unreleased)
### Added
- Added support for 1:N SMS messaging.
- Added support for SMS idempotency.
- Send method series in SmsClient are idempotent under retry policy.
- Added support for tagging SMS messages.

### Breaking
- Send method takes in strings for phone numbers instead of `PhoneNumberIdentifier`.
- Send method returns a list of `SmsSendResult`s instead of a `SendSmsResponse`.

## 1.0.0b5 (2021-02-09)
### Added
- Added support for Azure Active Directory authentication.
Expand Down
29 changes: 18 additions & 11 deletions sdk/communication/azure-communication-sms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ pip install azure-communication-sms
## Key concepts

Azure Communication SMS package is used to do following:
- Send an SMS
- Send SMS Messages

## Examples

The following section provides several code snippets covering some of the most common Azure Communication Services tasks, including:

- [Client Initialization](#client-initialization)
- [Sending an SMS](#sending-an-sms)
- [Sending SMS Messages](#sending--zsms)

### Client Initialization

Expand All @@ -54,23 +54,27 @@ endpoint = os.getenv('AZURE_COMMUNICATION_SERVICE_ENDPOINT')
sms_client = SmsClient(endpoint, DefaultAzureCredential())
```

### Sending an SMS
### Sending SMS Messages

Once the client is initialized, the `.send()` method can be invoked:

```Python
from azure.communication.sms import SendSmsOptions, PhoneNumberIdentifier
from azure.communication.sms import SendSmsOptions

smsresponse = sms_client.send(
sms_responses = sms_client.send(
from_phone_number=PhoneNumberIdentifier("<leased-phone-number>"),
to_phone_number=[PhoneNumberIdentifier("<to-phone-number>")],
to_phone_numbers=["<to-phone-number-1>", "<to-phone-number-2>", "<to-phone-number-3>"],
message="Hello World via SMS",
send_sms_options=SendSmsOptions(enable_delivery_report=True)) # optional property
enable_delivery_report=True, # optional property
ankitarorabit marked this conversation as resolved.
Show resolved Hide resolved
tag="custom-tag") # optional property
```

- `from-phone-number`: an SMS enabled phone number associated with your communication service
- `to-phone-number`: the phone number you wish to send a message to
- `send_sms_options`: an optional parameter that you can use to configure Delivery Reporting. This is useful for scenarios where you want to emit events when SMS messages are delivered.
- `from_phone_number`: An SMS enabled phone number associated with your communication service.
- `to_phone_numbers`: The phone numbers you wish to send a message to.
- `message`: The message that you want to send.
- `enable_delivery_report`: An optional parameter that you can use to configure delivery reporting. This is useful for scenarios where you want to emit events when SMS messages are delivered.
- `tag`: An optional parameter that you can use to configure custom tagging.


## Troubleshooting
The Azure Communication Service Identity client will raise exceptions defined in [Azure Core](https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/core/azure-core/README.md).
Expand All @@ -93,4 +97,7 @@ When you submit a pull request, a CLA-bot will automatically determine whether y
PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.

<!-- LINKS -->
[azure_core]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/core/azure-core/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
from ._sms_client import SmsClient

from ._shared.models import (
PhoneNumberIdentifier,
)

from ._generated.models import (
SendSmsOptions,
SendSmsResponse,
)
from ._models import SmsSendResult

__all__ = [
'SmsClient',
'PhoneNumberIdentifier',
'SendSmsOptions',
'SendSmsResponse',
'SmsSendResult',
]
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class AzureCommunicationSMSService(object):

:ivar sms: SmsOperations operations
:vartype sms: azure.communication.sms.operations.SmsOperations
:param endpoint: The endpoint of the Azure Communication resource.
:param endpoint: The communication resource, for example https://my-resource.communication.azure.com.
:type endpoint: str
"""

Expand All @@ -41,6 +41,7 @@ def __init__(

client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
self._serialize = Serializer(client_models)
self._serialize.client_side_validation = False
self._deserialize = Deserializer(client_models)

self.sms = SmsOperations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AzureCommunicationSMSServiceConfiguration(Configuration):
Note that all parameters used to create this instance are saved as instance
attributes.

:param endpoint: The endpoint of the Azure Communication resource.
:param endpoint: The communication resource, for example https://my-resource.communication.azure.com.
:type endpoint: str
"""

Expand All @@ -38,7 +38,7 @@ def __init__(
super(AzureCommunicationSMSServiceConfiguration, self).__init__(**kwargs)

self.endpoint = endpoint
self.api_version = "2020-07-20-preview1"
self.api_version = "2021-03-07"
ankitarorabit marked this conversation as resolved.
Show resolved Hide resolved
kwargs.setdefault('sdk_moniker', 'azurecommunicationsmsservice/{}'.format(VERSION))
self._configure(**kwargs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class AzureCommunicationSMSService(object):

:ivar sms: SmsOperations operations
:vartype sms: azure.communication.sms.aio.operations.SmsOperations
:param endpoint: The endpoint of the Azure Communication resource.
:param endpoint: The communication resource, for example https://my-resource.communication.azure.com.
:type endpoint: str
"""

Expand All @@ -36,6 +36,7 @@ def __init__(

client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)}
self._serialize = Serializer(client_models)
self._serialize.client_side_validation = False
self._deserialize = Deserializer(client_models)

self.sms = SmsOperations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AzureCommunicationSMSServiceConfiguration(Configuration):
Note that all parameters used to create this instance are saved as instance
attributes.

:param endpoint: The endpoint of the Azure Communication resource.
:param endpoint: The communication resource, for example https://my-resource.communication.azure.com.
:type endpoint: str
"""

Expand All @@ -33,7 +33,7 @@ def __init__(
super(AzureCommunicationSMSServiceConfiguration, self).__init__(**kwargs)

self.endpoint = endpoint
self.api_version = "2020-07-20-preview1"
self.api_version = "2021-03-07"
ankitarorabit marked this conversation as resolved.
Show resolved Hide resolved
kwargs.setdefault('sdk_moniker', 'azurecommunicationsmsservice/{}'.format(VERSION))
self._configure(**kwargs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from azure.core.pipeline import PipelineResponse
from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest

from ... import models
from ... import models as _models
ankitarorabit marked this conversation as resolved.
Show resolved Hide resolved

T = TypeVar('T')
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]
Expand All @@ -31,7 +31,7 @@ class SmsOperations:
:param deserializer: An object model deserializer.
"""

models = models
models = _models

def __init__(self, client, config, serializer, deserializer) -> None:
self._client = client
Expand All @@ -41,26 +41,26 @@ def __init__(self, client, config, serializer, deserializer) -> None:

async def send(
self,
send_message_request: "models.SendMessageRequest",
send_message_request: "_models.SendMessageRequest",
**kwargs
) -> "models.SendSmsResponse":
) -> "_models.SmsSendResponse":
"""Sends a SMS message from a phone number that belongs to the authenticated account.

Sends a SMS message from a phone number that belongs to the authenticated account.

:param send_message_request: Represents the body of the send message request.
:type send_message_request: ~azure.communication.sms.models.SendMessageRequest
:keyword callable cls: A custom type or function that will be passed the direct response
:return: SendSmsResponse, or the result of cls(response)
:rtype: ~azure.communication.sms.models.SendSmsResponse
:return: SmsSendResponse, or the result of cls(response)
:rtype: ~azure.communication.sms.models.SmsSendResponse
:raises: ~azure.core.exceptions.HttpResponseError
"""
cls = kwargs.pop('cls', None) # type: ClsType["models.SendSmsResponse"]
cls = kwargs.pop('cls', None) # type: ClsType["_models.SmsSendResponse"]
error_map = {
401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError
}
error_map.update(kwargs.pop('error_map', {}))
api_version = "2020-07-20-preview1"
api_version = "2021-03-07"
content_type = kwargs.pop("content_type", "application/json")
accept = "application/json"

Expand All @@ -87,11 +87,11 @@ async def send(
pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
response = pipeline_response.http_response

if response.status_code not in [200]:
if response.status_code not in [202]:
map_error(status_code=response.status_code, response=response, error_map=error_map)
raise HttpResponseError(response=response)

deserialized = self._deserialize('SendSmsResponse', pipeline_response)
deserialized = self._deserialize('SmsSendResponse', pipeline_response)

if cls:
return cls(pipeline_response, deserialized, {})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,26 @@

try:
from ._models_py3 import SendMessageRequest
from ._models_py3 import SendSmsOptions
from ._models_py3 import SendSmsResponse
from ._models_py3 import SmsRecipient
from ._models_py3 import SmsSendOptions
from ._models_py3 import SmsSendResponse
from ._models_py3 import SmsSendResponseItem
except (SyntaxError, ImportError):
from ._models import SendMessageRequest # type: ignore
from ._models import SendSmsOptions # type: ignore
from ._models import SendSmsResponse # type: ignore
from ._models import SmsRecipient # type: ignore
from ._models import SmsSendOptions # type: ignore
from ._models import SmsSendResponse # type: ignore
from ._models import SmsSendResponseItem # type: ignore

from ._azure_communication_sms_service_enums import (
SmsSendResponseItemRepeatabilityResult,
)

__all__ = [
'SendMessageRequest',
'SendSmsOptions',
'SendSmsResponse',
'SmsRecipient',
'SmsSendOptions',
'SmsSendResponse',
'SmsSendResponseItem',
'SmsSendResponseItemRepeatabilityResult',
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

from enum import Enum, EnumMeta
from six import with_metaclass

class _CaseInsensitiveEnumMeta(EnumMeta):
def __getitem__(self, name):
return super().__getitem__(name.upper())

def __getattr__(cls, name):
"""Return the enum member matching `name`
We use __getattr__ instead of descriptors or inserting into the enum
class' __dict__ in order to support `name` and `value` being both
properties for enum members (which live in the class' __dict__) and
enum members themselves.
"""
try:
return cls._member_map_[name.upper()]
except KeyError:
raise AttributeError(name)


class SmsSendResponseItemRepeatabilityResult(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
"""The result of a repeatable request with one of the case-insensitive values accepted or
rejected.
"""

ACCEPTED = "accepted"
REJECTED = "rejected"
Loading