Cannot connect to Azure IoT Hub with Qpid JMS client

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Cannot connect to Azure IoT Hub with Qpid JMS client

GowthamAG
The goal is to connect to Azure IoT Hub using Qpid jms client.

I am getting error as "javax.jms.JMSSecurityException: Received error from
remote peer without description [condition = amqp:unauthorized-access]"

I have tried below code
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for
full license information.


import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;

public class JmsTopicQuickstart2 {

    // number of messages to send
    private static int totalSend = 1;    

    public void run(String connectionString) throws Exception {

        // The connection string builder is the only part of the
azure-servicebus SDK library
        // we use in this JMS sample and for the purpose of robustly parsing
the Service Bus
        // connection string.
        ConnectionStringBuilder csb = new
ConnectionStringBuilder(connectionString);

        // set up the JNDI context
        Hashtable<String, String> hashtable = new Hashtable<>();
        hashtable.put("connectionfactory.SBCF",
"amqps://xxxxx.azure-devices.net?amqp.idleTimeout=120000");        
        hashtable.put("topic.TOPIC", "devices/device001/messages/events");        
        hashtable.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.qpid.jms.jndi.JmsInitialContextFactory");
        Context context = new InitialContext(hashtable);

        ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");

        // Look up the topic
        Destination topic = (Destination) context.lookup("TOPIC");

        // we create a scope here so we can use the same set of local
variables cleanly
        // again to show the receive side seperately with minimal clutter
        {
            // Create Connection
            Connection connection = cf.createConnection(csb.getSasKeyName(),
csb.getSasKey());
            connection.start();
            System.out.println("Started");
            // Create Session, no transaction, client ack
            Session session = connection.createSession(false,
Session.CLIENT_ACKNOWLEDGE);

            // Create producer
            MessageProducer producer = session.createProducer(topic);

            // Send messaGES
            for (int i = 0; i < totalSend; i++) {
                BytesMessage message = session.createBytesMessage();
                message.writeBytes(String.valueOf(i).getBytes());
                producer.send(message);
                System.out.printf("Sent message %d.\n", i + 1);
            }

            producer.close();
            session.close();
            connection.stop();
            connection.close();
        }      
    }    
    public static void main(String[] args) {

        //System.exit(runApp(args, (connectionString) -> {
            JmsTopicQuickstart2 app = new JmsTopicQuickstart2();
            String
connectionString="HostName=xxxx.azure-devices.net;DeviceId=device001;SharedAccessKey=XXXX";
            try {
                app.run(connectionString);
                //return 0;
            } catch (Exception e) {
           
                System.out.printf("%s", e.toString());
                System.out.println("\n"+e.getLocalizedMessage());
               // return 1;
            }
        //}));
    }
}

Can someone help me with this?



--
Sent from: http://qpid.2158936.n2.nabble.com/Apache-Qpid-users-f2158936.html

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

RE: [EXTERNAL] Cannot connect to Azure IoT Hub with Qpid JMS client

Connie Yau
Hey,

Is there a reason you're trying to use JMS? As far as I know, Azure IoT supports AMQP and MQTT (limited features). The IoT SDK uses AMQP (via proton-j). https://github.com/Azure/azure-iot-sdk-java

Cheers,
Connie

-----Original Message-----
From: GowthamAG <[hidden email]>
Sent: Wednesday, January 6, 2021 04:15
To: [hidden email]
Subject: [EXTERNAL] Cannot connect to Azure IoT Hub with Qpid JMS client

The goal is to connect to Azure IoT Hub using Qpid jms client.

I am getting error as "javax.jms.JMSSecurityException: Received error from remote peer without description [condition = amqp:unauthorized-access]"

I have tried below code
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.


import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;

public class JmsTopicQuickstart2 {

    // number of messages to send
    private static int totalSend = 1;    

    public void run(String connectionString) throws Exception {

        // The connection string builder is the only part of the azure-servicebus SDK library
        // we use in this JMS sample and for the purpose of robustly parsing the Service Bus
        // connection string.
        ConnectionStringBuilder csb = new ConnectionStringBuilder(connectionString);

        // set up the JNDI context
        Hashtable<String, String> hashtable = new Hashtable<>();
        hashtable.put("connectionfactory.SBCF",
"amqps://xxxxx.azure-devices.net?amqp.idleTimeout=120000");        
        hashtable.put("topic.TOPIC", "devices/device001/messages/events");        
        hashtable.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.qpid.jms.jndi.JmsInitialContextFactory");
        Context context = new InitialContext(hashtable);

        ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");

        // Look up the topic
        Destination topic = (Destination) context.lookup("TOPIC");

        // we create a scope here so we can use the same set of local variables cleanly
        // again to show the receive side seperately with minimal clutter
        {
            // Create Connection
            Connection connection = cf.createConnection(csb.getSasKeyName(),
csb.getSasKey());
            connection.start();
            System.out.println("Started");
            // Create Session, no transaction, client ack
            Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);

            // Create producer
            MessageProducer producer = session.createProducer(topic);

            // Send messaGES
            for (int i = 0; i < totalSend; i++) {
                BytesMessage message = session.createBytesMessage();
                message.writeBytes(String.valueOf(i).getBytes());
                producer.send(message);
                System.out.printf("Sent message %d.\n", i + 1);
            }

            producer.close();
            session.close();
            connection.stop();
            connection.close();
        }      
    }    
    public static void main(String[] args) {

        //System.exit(runApp(args, (connectionString) -> {
            JmsTopicQuickstart2 app = new JmsTopicQuickstart2();
            String
connectionString="HostName=xxxx.azure-devices.net;DeviceId=device001;SharedAccessKey=XXXX";
            try {
                app.run(connectionString);
                //return 0;
            } catch (Exception e) {
           
                System.out.printf("%s", e.toString());
                System.out.println("\n"+e.getLocalizedMessage());
               // return 1;
            }
        //}));
    }
}

Can someone help me with this?



--
Sent from: https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fqpid.2158936.n2.nabble.com%2FApache-Qpid-users-f2158936.html&amp;data=04%7C01%7Cconniey%40microsoft.com%7C7f26984cf0ef426ba03008d8b23e84e0%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637455329141125786%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=LPPl5jbowZ03U%2FJOZVN65fi2mWDe%2Fe4KxpCbY65f%2Bzg%3D&amp;reserved=0

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email] For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

RE: [EXTERNAL] Cannot connect to Azure IoT Hub with Qpid JMS client

GowthamAG
When i use Microsoft SDK to AMQP connection, it will be tightly coupled. In
future if i want to move from Azure IoT hub to other vendors i need to
change entire client code which is not feasible.



--
Sent from: http://qpid.2158936.n2.nabble.com/Apache-Qpid-users-f2158936.html

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Cannot connect to Azure IoT Hub with Qpid JMS client

Robbie Gemmell
Administrator
In reply to this post by GowthamAG
The exception text you mention probably suggests the client was
actually able to connect, and the program likely failed at a later
point due to the server refusing an operation due to access
permissions, e.g perhaps when creating the producer. I can only refer
you to Microsoft's documentation/support for such authz aspects.

If you printed the stacktrace instead of just toString()'ing it the
precise application/client behaviour would likely be clearer. Enabling
some client logging and/or protocol trace logging, would also show
more of what is happening and when,
http://qpid.apache.org/releases/qpid-jms-0.56.0/docs/index.html#logging


On Wed, 6 Jan 2021 at 12:28, GowthamAG <[hidden email]> wrote:

>
> The goal is to connect to Azure IoT Hub using Qpid jms client.
>
> I am getting error as "javax.jms.JMSSecurityException: Received error from
> remote peer without description [condition = amqp:unauthorized-access]"
>
> I have tried below code
> // Copyright (c) Microsoft. All rights reserved.
> // Licensed under the MIT license. See LICENSE file in the project root for
> full license information.
>
>
> import com.microsoft.azure.servicebus.primitives.ConnectionStringBuilder;
> import javax.jms.*;
> import javax.naming.Context;
> import javax.naming.InitialContext;
> import javax.naming.NamingException;
> import java.util.Hashtable;
> import java.util.Scanner;
> import java.util.concurrent.atomic.AtomicInteger;
> import java.util.function.Function;
>
> public class JmsTopicQuickstart2 {
>
>     // number of messages to send
>     private static int totalSend = 1;
>
>     public void run(String connectionString) throws Exception {
>
>         // The connection string builder is the only part of the
> azure-servicebus SDK library
>         // we use in this JMS sample and for the purpose of robustly parsing
> the Service Bus
>         // connection string.
>         ConnectionStringBuilder csb = new
> ConnectionStringBuilder(connectionString);
>
>         // set up the JNDI context
>         Hashtable<String, String> hashtable = new Hashtable<>();
>         hashtable.put("connectionfactory.SBCF",
> "amqps://xxxxx.azure-devices.net?amqp.idleTimeout=120000");
>         hashtable.put("topic.TOPIC", "devices/device001/messages/events");
>         hashtable.put(Context.INITIAL_CONTEXT_FACTORY,
> "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
>         Context context = new InitialContext(hashtable);
>
>         ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");
>
>         // Look up the topic
>         Destination topic = (Destination) context.lookup("TOPIC");
>
>         // we create a scope here so we can use the same set of local
> variables cleanly
>         // again to show the receive side seperately with minimal clutter
>         {
>             // Create Connection
>             Connection connection = cf.createConnection(csb.getSasKeyName(),
> csb.getSasKey());
>             connection.start();
>             System.out.println("Started");
>             // Create Session, no transaction, client ack
>             Session session = connection.createSession(false,
> Session.CLIENT_ACKNOWLEDGE);
>
>             // Create producer
>             MessageProducer producer = session.createProducer(topic);
>
>             // Send messaGES
>             for (int i = 0; i < totalSend; i++) {
>                 BytesMessage message = session.createBytesMessage();
>                 message.writeBytes(String.valueOf(i).getBytes());
>                 producer.send(message);
>                 System.out.printf("Sent message %d.\n", i + 1);
>             }
>
>             producer.close();
>             session.close();
>             connection.stop();
>             connection.close();
>         }
>     }
>     public static void main(String[] args) {
>
>         //System.exit(runApp(args, (connectionString) -> {
>             JmsTopicQuickstart2 app = new JmsTopicQuickstart2();
>             String
> connectionString="HostName=xxxx.azure-devices.net;DeviceId=device001;SharedAccessKey=XXXX";
>             try {
>                 app.run(connectionString);
>                 //return 0;
>             } catch (Exception e) {
>
>                 System.out.printf("%s", e.toString());
>                 System.out.println("\n"+e.getLocalizedMessage());
>                // return 1;
>             }
>         //}));
>     }
> }
>
> Can someone help me with this?
>
>
>
> --
> Sent from: http://qpid.2158936.n2.nabble.com/Apache-Qpid-users-f2158936.html
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Cannot connect to Azure IoT Hub with Qpid JMS client

Connie Yau
What Robbie says is correct, Azure uses claims-based authorization. Part of
the magic that the IoT SDK does is create a session to the $cbs node with
the correct payload. The information is here:
https://docs.microsoft.com/azure/service-bus-messaging/service-bus-amqp-protocol-guide#claims-based-authorization

A pointer to where the IoT client library does this magic is here:
https://github.com/Azure/azure-iot-sdk-java/blob/master/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/transport/amqps/AmqpsIotHubConnection.java#L247

Cheers,
Connie



--
Sent from: http://qpid.2158936.n2.nabble.com/Apache-Qpid-users-f2158936.html

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Cannot connect to Azure IoT Hub with Qpid JMS client

Robbie Gemmell
Administrator
It's always been my understanding that the use of CBS was optional.
Certainly, none of the Microsoft documentation I've seen around using
the JMS client (with Service Bus) refers to it that I can recall.

In looking at the original code from the first mail again, I see its
included 'Azure connection string'
("HostName=xxxx.azure-devices.net;DeviceId=device001;SharedAccessKey=XXXX")
only contains a SharedAccessKey value. From some searching I expect
there also needs to be a SharedAccessKeyName value too. These are both
seemingly used and passed when creating the connection from the
factory, effectively passed as the user/pass values:
"Connection connection = cf.createConnection(csb.getSasKeyName(),
csb.getSasKey());"

So if the getSasKeyName() return value is null/empty, then the client
will likely only be able to use the ANONYMOUS SASL mech(unless doing
TLS client certificate auth), assuming it is actually offered by the
server, which in this case I expect it would be since ANONYMOUS is a
key route CBS is used via. So I expect the client was able to connect
as I said before, but only anonymously as that was offered and it had
insufficient details to do anything else, but was as result then
unable to complete things such as creating the MessageProducer since
it was only 'anonymously authenticated' and so was denied
authorization having not done anything else like CBS usage.

Various links:
https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-java-how-to-use-jms-api-amqp
https://docs.microsoft.com/en-us/azure/service-bus-messaging/how-to-use-java-message-service-20
https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-create-namespace-portal#get-the-connection-string
https://github.com/Azure/azure-service-bus-java/blob/2.0.0/azure-servicebus/src/main/java/com/microsoft/azure/servicebus/primitives/ConnectionStringBuilder.java#L32-L33

On Mon, 11 Jan 2021 at 20:14, reifujin <[hidden email]> wrote:

>
> What Robbie says is correct, Azure uses claims-based authorization. Part of
> the magic that the IoT SDK does is create a session to the $cbs node with
> the correct payload. The information is here:
> https://docs.microsoft.com/azure/service-bus-messaging/service-bus-amqp-protocol-guide#claims-based-authorization
>
> A pointer to where the IoT client library does this magic is here:
> https://github.com/Azure/azure-iot-sdk-java/blob/master/device/iot-device-client/src/main/java/com/microsoft/azure/sdk/iot/device/transport/amqps/AmqpsIotHubConnection.java#L247
>
> Cheers,
> Connie
>
>
>
> --
> Sent from: http://qpid.2158936.n2.nabble.com/Apache-Qpid-users-f2158936.html
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Cannot connect to Azure IoT Hub with Qpid JMS client

Connie Yau
For each IoT Hub that is created, the default the [built-in
endpoint](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-messages-d2c#built-in-endpoint-as-a-routing-endpoint)
is Event Hubs. The CBS node is required if your backing datastore for IoTHub
is Event Hubs or Service Bus.

The CBS is is /not/ needed when you try to transform the IoT connection
string into an Event Hubs connection string. Any of the SASL mechanisms will
work with IoT Hub to get the redirect to the endpoint, but then you'll need
to authorize with the CBS node to connect to that redirected endpoint.

Here is a sample of transforming the IoT Hub Connection String to an Event
Hubs connection string.
Transform IoT Hub Connection String
<https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/eventhub/event-hubs/samples/typescript/src/iothubConnectionString.ts>  



--
Sent from: http://qpid.2158936.n2.nabble.com/Apache-Qpid-users-f2158936.html

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Cannot connect to Azure IoT Hub with Qpid JMS client

Robbie Gemmell
Administrator
I see, so you can use Service Bus and Event Hubs without CBS, but if
using them via IoT Hub you do need CBS. Really it seems like for
IoTHub the route is using Microsofts SDK.

Regardless, I see the transform example uses a link-redirection error
to get the secondary server details (though obviously it doesn't then
actually redirect the link). The JMS clients failover bits do handle
connection-redirect errors internally, but it doesn't and won't handle
link-redirects itself. I dont expect it is currently possible to
ascertain the info map details from the JMSException created if one is
encountered at present when creating a producer/consumer, only the
error type and description, so that would also rule out doing that
transform with the JMS client at present.

On Thu, 14 Jan 2021 at 19:33, reifujin <[hidden email]> wrote:

>
> For each IoT Hub that is created, the default the [built-in
> endpoint](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-messages-d2c#built-in-endpoint-as-a-routing-endpoint)
> is Event Hubs. The CBS node is required if your backing datastore for IoTHub
> is Event Hubs or Service Bus.
>
> The CBS is is /not/ needed when you try to transform the IoT connection
> string into an Event Hubs connection string. Any of the SASL mechanisms will
> work with IoT Hub to get the redirect to the endpoint, but then you'll need
> to authorize with the CBS node to connect to that redirected endpoint.
>
> Here is a sample of transforming the IoT Hub Connection String to an Event
> Hubs connection string.
> Transform IoT Hub Connection String
> <https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/eventhub/event-hubs/samples/typescript/src/iothubConnectionString.ts>
>
>
>
> --
> Sent from: http://qpid.2158936.n2.nabble.com/Apache-Qpid-users-f2158936.html
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [EXTERNAL] Re: Cannot connect to Azure IoT Hub with Qpid JMS client

Connie Yau
Hey,

Service Bus and Event Hubs both require CBS.

The redirect error is encountered if you use the IoT Hub Connection String to figure out what the backing data store's connection string is. You can bypass this dance by going to Azure Portal and copying the backing Event Hubs connection string.
https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messages-read-builtin#read-from-the-built-in-endpoint

Cheers,
Connie



Sent from Outlook<http://aka.ms/weboutlook>

________________________________
From: Robbie Gemmell <[hidden email]>
Sent: Friday, January 15, 2021 3:58 AM
To: users <[hidden email]>
Subject: [EXTERNAL] Re: Cannot connect to Azure IoT Hub with Qpid JMS client

I see, so you can use Service Bus and Event Hubs without CBS, but if
using them via IoT Hub you do need CBS. Really it seems like for
IoTHub the route is using Microsofts SDK.

Regardless, I see the transform example uses a link-redirection error
to get the secondary server details (though obviously it doesn't then
actually redirect the link). The JMS clients failover bits do handle
connection-redirect errors internally, but it doesn't and won't handle
link-redirects itself. I dont expect it is currently possible to
ascertain the info map details from the JMSException created if one is
encountered at present when creating a producer/consumer, only the
error type and description, so that would also rule out doing that
transform with the JMS client at present.

On Thu, 14 Jan 2021 at 19:33, reifujin <[hidden email]> wrote:

>
> For each IoT Hub that is created, the default the [built-in
> endpoint](https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.microsoft.com%2Fazure%2Fiot-hub%2Fiot-hub-devguide-messages-d2c%23built-in-endpoint-as-a-routing-endpoint&amp;data=04%7C01%7Cconniey%40microsoft.com%7C30aa446596264a9a9eb708d8b94cf342%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637463087444003230%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=Xr2ik%2FvEzefMX%2Fz10S6UiPp6W%2FWhy9AL04%2Bx4cdRFq8%3D&amp;reserved=0)
> is Event Hubs. The CBS node is required if your backing datastore for IoTHub
> is Event Hubs or Service Bus.
>
> The CBS is is /not/ needed when you try to transform the IoT connection
> string into an Event Hubs connection string. Any of the SASL mechanisms will
> work with IoT Hub to get the redirect to the endpoint, but then you'll need
> to authorize with the CBS node to connect to that redirected endpoint.
>
> Here is a sample of transforming the IoT Hub Connection String to an Event
> Hubs connection string.
> Transform IoT Hub Connection String
> <https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAzure%2Fazure-sdk-for-js%2Fblob%2Fmaster%2Fsdk%2Feventhub%2Fevent-hubs%2Fsamples%2Ftypescript%2Fsrc%2FiothubConnectionString.ts&amp;data=04%7C01%7Cconniey%40microsoft.com%7C30aa446596264a9a9eb708d8b94cf342%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637463087444003230%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=7gr8WAFC0OJ566ZkTDzMad2VmDoeOAXobP0fyED%2BWhs%3D&amp;reserved=0>
>
>
>
> --
> Sent from: https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fqpid.2158936.n2.nabble.com%2FApache-Qpid-users-f2158936.html&amp;data=04%7C01%7Cconniey%40microsoft.com%7C30aa446596264a9a9eb708d8b94cf342%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637463087444003230%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=f%2Bbq45c%2FaltCavmRVQ%2F6dedSWYslU8CQ7UXdRmHikAM%3D&amp;reserved=0
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]