Skip to content

Commit

Permalink
[Communication] Email commands in preview mode (#5825)
Browse files Browse the repository at this point in the history
* [Communication] update communication module version to 1.4.1, remove redundant version in setup

* [Communication] add email command group in preview mode

* fix typo in email status get parameter setup

* Add more help for email commands.
  • Loading branch information
mayssamm authored Feb 2, 2023
1 parent e84a3c3 commit fe52b57
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/communication/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
Release History
===============

1.5.0
++++++
* Add communication email command group in preview mode


1.4.1
++++++
* Update version missed in previous release
Expand Down
8 changes: 8 additions & 0 deletions src/communication/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,11 @@ az communication rooms participant update --room "roomId" --presenter-participan
```
az communication rooms participant remove --room "roomId" --participants "8:acs:xxxxxx" "8:acs:xxxxxx" "8:acs:xxxxxx" "8:acs:xxxxxx"
```
##### Send-Email #####
```
az communication email send --sender "NoReply@contoso.com" --subject "Contoso Update" --to "user1@user1-domain.com" "user2@user2-domain.com" --text "Hello valued client. There is an update."
```
##### Get-Email-Status #####
```
az communication email status get --message-id "01234567-89ab-cdef-0123-012345678901"
```
12 changes: 12 additions & 0 deletions src/communication/azext_communication/manual/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,15 @@ def cf_communication_rooms(cli_ctx, kwargs):

client = RoomsClient.from_connection_string(connection_string)
return client


def cf_communication_email(cli_ctx, kwargs):
from azure.communication.email import EmailClient

connection_string = kwargs.pop('connection_string', None)
if connection_string is None:
error_msg = 'Please specify --connection-string, or set AZURE_COMMUNICATION_CONNECTION_STRING.'
raise RequiredArgumentMissingError(error_msg)

client = EmailClient.from_connection_string(connection_string)
return client
28 changes: 28 additions & 0 deletions src/communication/azext_communication/manual/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,3 +504,31 @@
text: |-
az communication rooms participant remove --room "12345678901234567" --participants "8:acs:xxxxxx" "8:acs:xxxxxx" "8:acs:xxxxxx"
"""

helps['communication email'] = """
type: group
short-summary: Commands to send emails and get the status of emails previously sent using Azure Communication Services Email service.
"""

helps['communication email status'] = """
type: group
short-summary: Commands to get the status of emails previously sent using Azure Communication Services Email service.
"""

helps['communication email send'] = """
type: command
short-summary: "Send an email."
examples:
- name: Send an email from an existing domain
text: |-
az communication email send --sender "NoReply@contoso.com" --subject "Contoso Update" --to "user1@user1-domain.com" "user2@user2-domain.com" --text "Hello valued client. There is an update."
"""

helps['communication email status get'] = """
type: command
short-summary: "Get status of an email previously sent."
examples:
- name: Get status of an email
text: |-
az communication email status get --message-id "01234567-89ab-cdef-0123-012345678901"
"""
32 changes: 32 additions & 0 deletions src/communication/azext_communication/manual/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from azure.cli.core.commands.parameters import get_enum_type, get_three_state_flag


def load_arguments(self, _):
with self.argument_context('communication update') as c:
Expand All @@ -13,6 +15,7 @@ def load_arguments(self, _):
_load_phonenumber_arguments(self)
_load_chat_arguments(self)
_load_rooms_arguments(self)
_load_email_arguments(self)


def _load_identity_arguments(self):
Expand Down Expand Up @@ -242,3 +245,32 @@ def _load_rooms_arguments(self):
type=str, help='Room Id')
c.argument('participants', options_list=['--participants'],
nargs='+', help='Collection of identities that will be removed from the room.')


def _load_email_arguments(self):
with self.argument_context('communication email send') as c:
c.argument('sender', options_list=['--sender'], type=str, help='Sender email address from a verified domain.')
c.argument('subject', options_list=['--subject'], type=str, help='Subject of the email message.')
c.argument('text', options_list=['--text'], type=str, help='Plain text version of the email message. Optional.')
c.argument('html', options_list=['--html'], type=str, help='Html version of the email message. Optional.')
c.argument('importance', options_list=['--importance'], arg_type=get_enum_type(['normal', 'low', 'high']),
help='The importance type for the email. Known values are: high,'
' normal, and low. Default is normal. Optional')
c.argument('recipients_to', options_list=['--to'], nargs='+', help='Recepients email addresses.')
c.argument('recipients_cc', options_list=['--cc'], nargs='+', help='Carbon copy email addresses.')
c.argument('recipients_bcc', options_list=['--bcc'], nargs='+', help='Blind carbon copy email addresses.')
c.argument('reply_to', options_list=['--reply-to'], type=str, help='Reply-to email address. Optional.')
c.argument('disable_tracking', options_list=['--disable-tracking'], arg_type=get_three_state_flag(),
help='Indicates whether user engagement tracking should be disabled for this request if'
'the resource-level user engagement tracking setting was already enabled. Optional.')
c.argument('attachments', options_list=['--attachments'], nargs='+',
help='List of email attachments. Optional.')
c.argument('attachment_types', options_list=['--attachment-types'], nargs='+',
help='List of email attachment types, in the same order of attachments.'
' Required for each attachment. Known values are: avi, bmp, doc, docm,'
' docx, gif, jpeg, mp3, one, pdf, png, ppsm, ppsx, ppt, pptm, pptx,'
' pub, rpmsg, rtf, tif, txt, vsd, wav, wma, xls, xlsb, xlsm, and xlsx')

with self.argument_context('communication email status get') as c:
c.argument('message_id', options_list=['--message-id'], type=str,
help='System generated message id (GUID) returned from a previous call to send email')
12 changes: 12 additions & 0 deletions src/communication/azext_communication/manual/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from azext_communication.manual._client_factory import cf_communication_phonenumbers
from azext_communication.manual._client_factory import cf_communication_chat
from azext_communication.manual._client_factory import cf_communication_rooms
from azext_communication.manual._client_factory import cf_communication_email


def load_command_table(self, _):
Expand All @@ -17,6 +18,7 @@ def load_command_table(self, _):
_load_phonenumber_command_table(self)
_load_chat_command_table(self)
_load_rooms_command_table(self)
_load_email_command_table(self)


def _load_identity_command_table(self):
Expand Down Expand Up @@ -102,3 +104,13 @@ def _load_rooms_command_table(self):
g.communication_custom_command('add', 'communication_rooms_add_participants', rooms_arguments)
g.communication_custom_command('update', 'communication_rooms_update_participants', rooms_arguments)
g.communication_custom_command('remove', 'communication_rooms_remove_participants', rooms_arguments, confirmation=True)


def _load_email_command_table(self):
rooms_arguments = ['connection_string']
self.command_group('communication email', is_preview=True)

with self.command_group('communication email', client_factory=cf_communication_email, is_preview=True) as g:
g.communication_custom_command('send', 'communication_email_send', rooms_arguments)
with self.command_group('communication email', client_factory=cf_communication_email, is_preview=True) as g:
g.communication_custom_command('status get', 'communication_email_get_status', rooms_arguments)
87 changes: 87 additions & 0 deletions src/communication/azext_communication/manual/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,90 @@ def communication_rooms_remove_participants(client, room_id, participants):
raise
except Exception as ex:
sys.exit(str(ex))


def __get_attachment_content(filename, filetype):
import base64
import os
from azure.communication.email import EmailAttachment

_, tail = os.path.split(filename)
with open(filename, "r", encoding="utf-8") as file:
file_content = file.read()

base64_content = base64.b64encode(bytes(file_content, 'utf-8'))

return EmailAttachment(
name=tail,
attachment_type=filetype,
content_bytes_base64=base64_content.decode(),
)


def communication_email_send(client,
subject,
sender,
recipients_to,
disable_tracking=False,
text=None,
html=None,
importance='normal',
recipients_cc=None,
recipients_bcc=None,
reply_to=None,
attachments=None,
attachment_types=None):

from azure.communication.email import EmailContent, EmailAddress, EmailMessage, EmailRecipients
from knack.util import CLIError

try:
email_content = EmailContent(
subject=subject,
plain_text=text,
html=html,
)

to_address = [EmailAddress(email=r) for r in recipients_to]

reply_to_address = None if reply_to is None else [EmailAddress(email=reply_to)]

if attachments is None and attachment_types is None:
attachments_list = None
elif attachments is None or attachment_types is None:
raise CLIError('Number of attachments and attachment-types should match.')
elif len(attachments) != len(attachment_types):
raise CLIError('Number of attachments and attachment-types should match.')
else:
attachments_list = [
__get_attachment_content(attachments[i], attachment_types[i])
for i in range(len(attachments))
]

message = EmailMessage(
sender=sender,
content=email_content,
recipients=EmailRecipients(
to=to_address,
cc=[] if recipients_cc is None else [EmailAddress(email=r) for r in recipients_cc],
bcc=[] if recipients_bcc is None else [EmailAddress(email=r) for r in recipients_bcc]),
importance=importance,
reply_to=reply_to_address,
disable_user_engagement_tracking=disable_tracking,
attachments=attachments_list,
)

return client.send(message)
except HttpResponseError:
raise
except Exception as ex:
sys.exit(str(ex))


def communication_email_get_status(client, message_id):
try:
return client.get_send_status(message_id)
except HttpResponseError:
raise
except Exception as ex:
sys.exit(str(ex))
2 changes: 1 addition & 1 deletion src/communication/azext_communication/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# --------------------------------------------------------------------------------------------


VERSION = '1.4.1'
VERSION = '1.5.0'


def cli_application_id():
Expand Down
1 change: 1 addition & 0 deletions src/communication/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
'azure-communication-sms',
'azure-communication-chat',
'azure-communication-rooms',
'azure-communication-email >= 1.0.0b1',
]

try:
Expand Down

0 comments on commit fe52b57

Please sign in to comment.