Giter Club home page Giter Club logo

fuelsdk-node-soap's People

Contributors

aydrian avatar dougmidgley avatar jimmyburgess avatar jimmyburgess91 avatar kellyjandrews avatar manivinesh avatar nlf avatar sabrinaluo avatar sf-csarov avatar sfdrogojan avatar snyk-community avatar svc-scm avatar timsim00 avatar vernak2539 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fuelsdk-node-soap's Issues

Missing ability to specify Client IDs in each method.

Discovered by @jimmyburgess. This is a node on the same level as Properties and Options (if applicable).

      <ClientIDs>
         <ID>100000</ID>
      </ClientIDs>

As a JSON object it would look like:

ClientIDs: { ID: [ 1000 ] }

It would be best if we could introduce a fix that would not create a breaking change. In the create/update/delete methods, we could utilize the options parameter, but there is no options parameter for retrieve.

Create an email send definition using a filter definition

Im trying to create an email send definition with a filter definition included as well. I was able to create the email send definition with out the filter, however when I include the filter I get the error "A problem occurred processing your request" and an error code of "9999999".

let op = {
"Name": "Test",
"CustomerKey": "CustomerKey",
"Email": {
  "ID":"1234",
  "IDSpecified":true
},
"SendClassification":{
  "ObjectID":"5casd215basd2f-d261238-e811g5-80d3-11402asdec8196c8"
},
"SendDefinitionList":[
  {
    "CustomerKey": "Customerkey2",
    "FilterDefinition": {
        "Name" : "test",
        "CustomerKey": "Customerkey3",
        "DataFilter": {
            "Property" : "EmailAddress", 
            "SimpleOperator" : "equals",
            "Value": "[email protected]"
        }
    },
    "List": {
        "CustomerKey" : "1vbdksadg14avasdoj8ad124ngfcva1265"
    },
    "DataSourceTypeID": 'FilterDefinition',
    "SendDefinitionListType": "SourceList"
      }
    ],
 };

 SoapClient.create('EmailSendDefinition',op,(err, response) => {
    if ( err ) {
        console.log( err);
    }
    else{
      console.log( response);
    }
 });

When I try to create just the filter definition I get the error of "The DataFilter that was provided is invalid." and a code of "373009".

let co = {
    "Name" : "test",
    "CustomerKey": "CustomerKey",
    "DataFilter": {
        "Property" : "EmailAddress",
        "SimpleOperator": "equals",
        "Value": "[email protected]"
    }
}

  SoapClient.create('FilterDefinition',co,(err, response) => {
    if ( err ) {
      console.log( err);
    }

Any ideas?

Handling responses with Results

For responses with results, we need to make sure Results is an array. If the Results element isn't present, Results should equal an empty array. If only one Result is returned, Results should be an array of one result object. The parseString function handles multiple Results correctly. We can't use the explicitArray option because we don't want this behavior applied to all nodes.

The Describe response doesn't have a Results node.

Add to default headers at time of initialization

Give ability to a global default header, which is passed in at the time of init.

Test to pass (should be added to general-tests.js)

it('should add header from options to global headers (this.defaultHeaders)', function() {
    // Arrange
    var client;
    initOptions.headers = { newHeader: true };

    // Act
    client = new FuelSoap(initOptions);

    // Assert
    assert.ok(client.defaultHeaders.newHeader);
});

Cert Error

Hey

I am using FuelSDK-Node and getting an error.

Node: v4.1.2

Error message:

{ 
    [Error: unable to get local issuer certificate]
    code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
    errorPropagatedFrom: 'Request Module inside soapRequest' 
} 

Error: unable to get local issuer certificate
    at Error (native)
    at TLSSocket.<anonymous> (_tls_wrap.js:1000:38)
    at emitNone (events.js:67:13)
    at TLSSocket.emit (events.js:166:7)
    at TLSSocket._finishInit (_tls_wrap.js:567:8)

Adding:

rejectUnauthorized: false to Requests options corrects the issue but is probably not a long term solution.

Schedule soap action: "Cannot set property '$' of undefined"

Hi,
I'm using this package and tackled some bug with scheduling an Email Send Definition:
https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/scheduling_an_email_send_definition.htm

I'm trying to run this code to preform the action:

schedule() {
   ...

    const scheduleOpts = {
        Recurrence: {
            DailyRecurrencePatternType: 'Interval',
            DayInterval: 1,
        },
        RecurrenceType: 'Daily',
        RecurrenceRangeType: 'EndAfter',
        StartDateTime: '2021-02-28T22:00:00+02:00',
    }
    const interactions = { CustomerKey: ${EMAIL_DEFINITION_KEY} };

    return new Promise((resolve, reject) => {
        this.soapClient.schedule('EmailSendDefinition', scheduleOpts, interactions, 'start', null, (err, response) => {
            if (err) reject(err);
            else resolve(response.body);
        });
    });
}

But I get this error:

TypeError: Cannot set property '$' of undefined
    at FuelSoap.schedule (node_modules/fuel-soap/lib/fuel-soap.js:663:54)
    ....

Looking at the code I can see that there is an assignment to undefined property (in lib/fuel-soap.js line 663)

if(Array.isArray(body.ScheduleRequestMsg.Interactions)){
	for(let i = 0; i < body.ScheduleRequestMsg.Interactions.length; i++){
		body.ScheduleRequestMsg.Interactions[0].Interaction.$ = {'xsi:type': type};
	 }
} else if (typeof body.ScheduleRequestMsg.Interactions === "object") {
	body.ScheduleRequestMsg.Interactions.Interaction.$ = {'xsi:type': type};
} else {
	throw new TypeError('Interactions must be of Array or Object Type');
}

You can't assume that body.ScheduleRequestMsg.Interactions.Interaction.$ is set since you get it from outside.

Not sure this is a bug or I missed something in the docs (also didn't find much relevant docs on how to use the schedule action).
My version is 2.2.4

Thanks
Avishay

Custom header

I need to create a pull request to allow for custom headers so we can track usage of the new node SDK. Alex, do you have a preference for how that comes through? I can add another parameter after the callback. Or I could add it to the 'options' parameter and remove it from the options object after I process it. Thoughts?

Passing in batch size

I would like to pass in BatchSize as part of the RetrieveRequest.Options as outlined here but this doesn't seem to be possible right now.

var options = {
   options: {
      batchSize: 200,
   }
}

Exactly how do I add a subscriber to a list?

I'm getting super confused on how to set up the call to soapClient.create().

Do I set up options like this:

options = [{
    Name: 'SubscriberKey',
    Value: subscriberKey
  }, {
    Name: 'EmailAddress',
    Value: emailAddress
  }, {
    Name:  'ListID',
    Value: listID
  }];

then call the create() method as so? (Our subscriberKeys are emailAddresses btw).

soapClient.create( 'Subscriber', options, function( err, response )

When I do this I get TypeError: Uncaught error: Cannot read property 'toString' of undefined somewhere deep in xml2js.

Any pointers?

Any advice on creating a SoapClient.IET_Client.SoapClient.perform( ?

I'm trying to do an IET_Client.SoapClient.perform(.
Something like:
IET_Client.SoapClient.perform(
'EmailSendDefinition',
options,
function( err, response ) {...`

    var options = {
        props: {
            "Action": "start"
            , "CustomerKey": "2177425"
            , "SenderProfile": {
                "FromName": "Sender"
                , "FromAddress": "[email protected]"
            }
        }
    };

IET_Client.SoapClient.retrieve works well for me, but I am trying to figure out the structure for a perform.

Retrieve call is overly simple

We should look at expanding the retrieve call. Currently we accept type, fields to return, and a filter. We need to support getting more results if "MoreDataAvailable" is returned. There is also ClientIDs, QueryAllAccounts, and Retrieve Options and some others. It would be nice to get a better function signature in place before we release this to the world.

Open to suggestions.

Is it possible to make a PerformRequest?

I ma trying to execute an email send, but the .perform() method doesn't seem to do anything. I am able to retrieve the email's SendDefinition, but can't figure out how to actually execute the send. Can you please provide an example?

Update/Add tests

Problem
At the moment, test coverage is not the best, making it harder to make changes without knowing if something was broken.

Solution
Put unit tests around existing code. Will focus on more TDD style of tests

Coverage below after the merge of #86

=============================== Coverage summary ===============================
Statements   : 78.71% ( 196/249 )
Branches     : 67.96% ( 70/103 )
Functions    : 72.41% ( 21/29 )
Lines        : 78.71% ( 196/249 )
================================================================================

Implement retry on expired tokens

Since we are using access tokens, we need to be able to retry if the token happens to be expired. Similar to Fuel-REST but completely different.

Infer stack?

Is it possible to query the user's stack using just their client ID and secret?

Add type definitions

For those of us using Typescript or similar, it would be nice if there were some type definitions for this library.

I looked for a types package in NPM under the standard @types namespace but it appears none has been created:

$ npm install -D @types/fuel-soap
> npm ERR! code E404
> npm ERR! 404 Not Found: @types/fuel-soap@latest
> ...

Transition all function to take two params

Problem
It seems that most of the functions have different numbers of parameters. This makes it difficult to write code that can be reused. This will enable the implementation of promises to go faster

FuelSoap.prototype.delete = function(type, props, options, callback) {
FuelSoap.prototype.describe = function(type, callback) {

Proposed Solution
Transition to use only two parameters in every function, options and callback

FuelSoap.prototype.delete = function(options, callback) {
FuelSoap.prototype.describe = function(options, callback) {

Use initialized FuelAuth

Allow SOAP client to accept an already initialized FuelAuth instead of initializing it's own. Keep parity with Fuel-Node-REST.

Request: Deprecated & Security Issue

The Request package through 2.88.2 for Node.js allows a bypass of SSRF mitigations via an attacker-controller server that does a cross-protocol redirect (HTTP to HTTPS, or HTTPS to HTTP). NOTE: This vulnerability only affects products that are no longer supported by the maintainer.

Issue on FueAuth

I am using FuelSoap with FuelAuth and running into an issue on setting up the client.

var FuelAuthClient = new FuelAuth({
    clientId: clientId,
    clientSecret: clientSecret,
    authUrl: authOrigin,
    authOptions: {
        authVersion: 2
    }
});

FuelAuthClient.getAccessToken()
    .then(function (data) {
        // data.accessToken = your token
        // data.expiresIn = how long until token expiration
        console.log(data);

        var SoapClient = new FuelSoap(FuelAuthClient);

        SoapClient.retrieve(
            'Email',
            ["ID", "Name", "Subject", "CategoryID", "EmailType"],
            options,
            function (err, response) {
                if (err) {
                    // error here
                    console.log(err);
                    return;
                }

                // response.body === parsed soap response (JSON)
                // response.res === full response from request client
                console.log(response.body);
            }


        )
    })
    .catch(function (err) {
        console.log(err);
    });

The issue I am facing is in the FuelSoap initialization where it checks to see if its an instance of FuelAuth.

	var authOptions = options && options.auth || {};

	// use fuel auth instance if applicable
	if(authOptions instanceof  FuelAuth) {
		this.AuthClient = authOptions;
	} else {
		try {
			this.AuthClient = new FuelAuth(authOptions);
		} catch (err) {
			throw err;
		}
	}```

It looks like this line `var authOptions = options && options.auth || {};` is creating an empty object, expecting that `options.auth` exists. Well, when using the `FuelAuth` object, thats not the case so it defaults `authOptions = {}`.

This causes the `if(authOptions instanceof  FuelAuth) {` to return false and it tries to initialize `FuelAuth` using the `authOptions` which is an empty object. This throws an error in `FuelAuth`  about `Error: clientId or clientSecret is missing or invalid`.

To summarize, `if(authOptions instanceof  FuelAuth) {` returns false when using `FuelAuth` because `options.auth` doesn't exist which causes `authOptions` to be set to an empty object.

Allow for use without "new" keyword

Overview
Some people forget to use the new keyword when instantiating an object. All the Fuel Node.js SDKs used to require the use of new, but in order to be more flexible, we want to allow for use without new.

Test to get passing
This test should go in ./test/specs/general-tests.js

it('should not need to use "new" when instantiating', function() {
    // Arrange
    var nonConstructorFuelSOAP= require('../../lib/fuel-soap');
    var options = {
        auth: {
            clientId: '<test>'
            , clientSecret: '<test>'
        }
    };

    // Act
    var client = nonConstructorFuelSOAP(options);

    // Assert
    expect(client.requestOptions.method).to.equal('POST');
});

FuelSoap.prototype.Perform assumes action=start

Action=start is not the only value allowed for perform operations, in the SOAP API.
For example, there is also a ClearData action:

Clear Data from a Data Extension

<PerformRequestMsg xmlns="http://exacttarget.com/wsdl/partnerAPI" xmlns:ns2="urn:fault.partner.exacttarget.com">
      <Action>ClearData</Action>
      <Definitions>
            <Definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="DataExtension">
                  <CustomerKey>Test Data Extension</CustomerKey>
            </Definition>
      </Definitions>
</PerformRequestMsg>

There can also be an Options node in there, at the same level as Action.

This prototype should have had an action and an options parameter.
How about an overload to avoid breaking changes?

JSCS Integration

Will probably be as easy as copying dot file from FuelSDK-Node-REST over to this and implementing grunt task

  • Add .jscsrc file
  • Update files, fixing errors
  • Implement grunt task

Fix callback+option decision tree in retrieve function

Problem
When using the retrieve method in form of retrieve('type', options, callback) the requests body is not formed properly due to the fact it's trying to pull clientIDs and filter off the callback. An example below.

Also, it's not evident until looking at the code that during this usage, props becomes options

// sets clientIDs and filter (not correct)
var sampleCallback = function() {};
sampleCallback.clientIDs = [1,2,3,4];
sampleCallback.filter = { filter: true };

retrieve('Test', {}, sampleCallback);

Solution
We need to use the options passed to get the clientIDs and filter. It would be nice for the code to make clear that props are really options in this case also.

// sets clientIDs and filter correctly
var options = {}; 
options.clientIDs = [1,2,3,4];
options.filter = { filter: true };

retrieve('Test', options, function() {});

Give a little love

This module has been overlooked for a while, it's time to give it some love.

This could include

  1. Basic efactoring
  2. Making things easier to read
  3. Removal of unneeded deps/dev deps
  4. Removal of full lodash library in favour of individual modules
  5. Update to tests (moved to #91)
  6. JSCS integration (moved to #90)
  7. Clean up

I am getting following error in retrieving query definition status.

Following is my SOAP envelope ...

{ uri: 'https://webservice.s6.exacttarget.com/Service.asmx',
  method: 'POST',
  headers: 
   { 'User-Agent': 'node-fuel/1.3.1',
     'Content-Type': 'text/xml',
     SOAPAction: 'Retrieve' },
  body: '
<Envelope
    xmlns="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\n  
    <Header>\n    
        <To>https://webservice.s6.exacttarget.com/Service.asmx</To>\n    
        <fueloauth
            xmlns="http://exacttarget.com">XXXXXXXXXXXXXXXXXXXX
        </fueloauth>\n  
    </Header>\n  
    <Body>\n    
        <RetrieveRequestMsg
            xmlns="http://exacttarget.com/wsdl/partnerAPI">\n      
            <RetrieveRequest>\n        
                <ObjectType>AsyncActivityStatus</ObjectType>\n        
                <Properties>Status</Properties>\n        
                <Properties>StatusMessage</Properties>\n        
                <Client>\n          
                    <ID>XXXXXXX</ID>\n        
                </Client>\n        
                <Filter xsi:type="SimpleFilterPart">\n          
                    <Property>TaskID</Property>\n          
                    <SimpleOperator>equals</SimpleOperator>\n          
                    <Value>13XXXX</Value>\n        
                </Filter>\n      
            </RetrieveRequest>\n    
        </RetrieveRequestMsg>\n  
    </Body>\n
</Envelope>' }

I am getting following error while retrieving Query definition status

{ Error: read ECONNRESET
    at exports._errnoException (util.js:953:11)
    at TLSWrap.onread (net.js:563:26)
  code: 'ECONNRESET',
  errno: 'ECONNRESET',
  syscall: 'read',
  errorPropagatedFrom: 'Request Module inside soapRequest' }

Please tell me what was the cause of this and how to handle it.

how to retrieve all lists to which a single subscriber is subscribed

If I have the subscriberKey, and assuming I have all the auth set up, how do I use fuel-soap to find the lists to which a single subscriber is subscribed?

Is it something like this?

var index = function( request, reply ) {
  var subscriberKey = request.query.qs;
  var filter = {
      leftOperand: 'SubscriberKey',
      operator: 'equals',
      rightOperand: subscriberKey
    };
    soapClient.retrieve(
      'SubscriberList',
      ['Status'],
      filter,
      function( err, response ) {
        console.log( response.body );
      }
    );
  }
};

UpdateRequest "Requested value 'APIObject' was not found."

Hi Developers.
I am using fuel-soap for updating a DataExtensionObject and I was receiving a "Requested value 'APIObject' was not found." error.
I tracked the issue down to line 305 at lib/fuel-soap.js

body.UpdateRequest.Objects.$ = { 'xsi:type': type };

That line was adding an extra Objects XML tag to the body:

<Body>
  <UpdateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI">
    ...
    <Objects>
      <xsi:type>DataExtensionObject</xsi:type>
    </Objects>
  </UpdateRequest>
</Body>

When I commented that line, I started receiving the expected response.
So my question is, is that line necessary? Or am I doing something wrong?


Here is the exact request XML being generated with some props & options (with that line of code):

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Header>
    <fueloauth xmlns="http://exacttarget.com">7BmEgYaQZRrAXAS5uJmM8MOo</fueloauth>
  </Header>
  <Body>
    <UpdateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI">
      <Options>
        <SaveOptions>
          <SaveOption>
            <PropertyName>DataExtensionObject</PropertyName>
            <SaveAction>UpdateAdd</SaveAction>
          </SaveOption>
        </SaveOptions>
      </Options>
      <Objects xsi:type="DataExtensionObject">
        <CustomerKey>Consolidated_Opt_Out_table</CustomerKey>
        <Keys>
          <Key>
            <Name>Customer_Id</Name>
            <Value>XXXXXXXXX</Value>
          </Key>
          <Key>
            <Name>BrandName__c</Name>
            <Value>brandname</Value>
          </Key>
          <Key>
            <Name>Channel__c</Name>
            <Value>Email</Value>
          </Key>
        </Keys>
        <Properties>
          <Property>
            <Name>Newsletter__c</Name>
            <Value>false</Value>
          </Property>
          <Property>
            <Name>Newsletter_Date__c</Name>
            <Value>2017-02-14</Value>
          </Property>
        </Properties>
      </Objects>
      <Objects>
        <xsi:type>DataExtensionObject</xsi:type>
      </Objects>
    </UpdateRequest>
  </Body>
</Envelope>

Hostname/IP doesn't match certificate's altnames: "Host: webservice.s1.exacttarget.com. is not in the cert's altnames: DNS:ws-thehartford.exacttarget.com

I am getting following error while retrieving Data Extension.

{ Error: Hostname/IP doesn't match certificate's altnames: "Host: webservice.s1.exacttarget.com. is not in the cert's altnames: DNS:ws-thehartford.exacttarget.com"
    at Object.checkServerIdentity (tls.js:203:15)
    at TLSSocket.<anonymous> (_tls_wrap.js:1061:29)
    at emitNone (events.js:86:13)
    at TLSSocket.emit (events.js:185:7)
    at TLSSocket._finishInit (_tls_wrap.js:580:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:412:38)
  reason: 'Host: webservice.s1.exacttarget.com. is not in the cert\'s altnames: DNS:ws-thehartford.exacttarget.com',
  host: 'webservice.s1.exacttarget.com.',
  cert: 
   { subject: 
      { C: 'US',
        ST: 'Indiana',
        L: 'Indianapolis',
        O: 'ExactTarget, Inc',
        OU: 'Infrastructure',
        CN: 'ws-thehartford.exacttarget.com' },
     issuer: 
      { C: 'US',
        O: 'DigiCert Inc',
        CN: 'DigiCert SHA2 Secure Server CA' },
     subjectaltname: 'DNS:ws-thehartford.exacttarget.com',
     infoAccess: { 'OCSP - URI': [Object], 'CA Issuers - URI': [Object] },
     modulus: 'DDDDDDD',
     exponent: '1x15551',
     valid_from: 'Nov  2 00:00:00 2015 GMT',
     valid_to: 'Jan 30 12:00:00 2019 GMT',
     fingerprint: 'Removed',
     ext_key_usage: [Removed ],
     serialNumber: 'Removed',
     raw: Removed }

Please help me.
Thanks

Readme example is wrong.

SoapClient.retrieve(
'Email',
["ID", "Name", "Subject", "CategoryID", "EmailType"],
{"options":options},

Should be...

SoapClient.retrieve(
'Email',
["ID", "Name", "Subject", "CategoryID", "EmailType"],
options,

UNABLE_TO_GET_ISSUER_CERT_LOCALLY

Adding

requestOptions.rejectUnauthorized = false;

after line 106 in lib/fuel-soap.js fixed what appears to be a certificate issue at the service.

node 0.8

If we want this to work in node versions 0.8.x, we will have to eliminate all carets from the package.json.

This is the only one I see. just a heads up

Improve test coverage

Used the following command from project root directory to generate coverage (need istanbul and mocha installed globally.

istanbul cover _mocha test/specs

=============================== Coverage summary ===============================
Statements : 70.79% ( 126/178 )
Branches : 53.49% ( 46/86 )
Functions : 62.5% ( 15/24 )
Lines : 70.79% ( 126/178 )

Token Expired issues

When SOAP request is running and instantly token is expired then my SOAP request is failed. I need some suggestion which automatically generate new access token if this expired. without single point of SOAP request failure.

Please provide me fix of this issue with an example.

Thanks in advance.

Retrieving with a Filter in ReadMe is wrong

retrieve( type, props, filter, callback )
type - object type. see object types required
props - object properties to be returned required
filter - filter object

Should be:

filter - { filter: {leftOperand...} }

Because actual code in fuel-soap.js is

186: filter = options.filter;

Weird mocha behavior

Very strange behavior observed with mocha. The order of the test files makes a difference. The issue is around function-soapRequest. I tried putting a new test in there after the 'describe' test but it always resulted in "Error: connect ECONNRESET" in the midst of reporting a test. Also, reporting indicated that certain tests were ran twice. Very strange stuff.

Prefixing a file with _ causes the file to be processed first. This worked for node 0.8x but caused it fail on 0.10x, or vice versa, I don't remember. Some of this may have been my mac. I ended up getting both 0.8 and 0.10 tests to work on another machine. But I had to call it "header-test" so it ran after the other tests.

Error while updating email send definition using SOAP request

Following is my SOAP envelope

{ uri: 'https://webservice.s6.exacttarget.com/Service.asmx',
      method: 'POST',
      headers: 
       { 'User-Agent': 'node-fuel/1.3.1',
         'Content-Type': 'text/xml',
         SOAPAction: 'Update' },
      body: '
    <Envelope
        xmlns="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\n  
        <Header>\n    
            <To>https://webservice.s6.exacttarget.com/Service.asmx</To>\n    
            <fueloauth
                xmlns="http://exacttarget.com">xxxxxxxxxxxxxxxx
            </fueloauth>\n  
        </Header>\n  
        <Body>\n    
            <UpdateRequest
                xmlns="http://exacttarget.com/wsdl/partnerAPI">\n      
                <Options/>\n      
                <Objects xsi:type="EmailSendDefinition">\n        
                    <CustomerKey>1504XXXXXXXXX</CustomerKey>\n        
                    <EmailSubject>➡ Application required: we\'ve got the job for you - Tesco and Experian are recruiting today</EmailSubject>\n        
                    <Client>\n          
                        <ID>xxxxxxx</ID>\n        
                    </Client>\n      
                </Objects>\n    
            </UpdateRequest>\n  
        </Body>\n
    </Envelope>' }

I am getting following error :

{ "StatusCode": "Error", "StatusMessage": "Exception occurred during [UpdateEmailSendDefinition] ErrorID = 497866104",
"OrdinalID": "0", "ErrorCode": "9999999", "Object": { "Client": { "ID": "XXXXXX" }, "PartnerKey": "", "ObjectID": "xxxxx-xxxx-xxxx-xxxxx-xxxxxxx", "CustomerKey": "XXXXXXXXXXXXXXXXX", "EmailSubject": "➡ Application required: we've got the job for you - Tesco and Experian are recruiting today" } }

subscribing and unsubscribing users from lists

There are some really good docs on subscribing a user to a list here:

https://code.exacttarget.com/apis-sdks/soap-api/adding-subscribers-to-a-list.html

Because the examples use PHP, Java, and .NET -- it's a little hard to translate to fuel-node-soap.

In the edited fragment below, I can successfully subscribe someone to a list without a problem: First I i try to create the subscriber on the list; if I learn the subscriber already exists I do an update.

I have no trouble unsubscribing them from the list too (not shown here).

However, if I try to subscribe the Subscriber again, when the Subscriber already has a status of 'Unsubscribed', I am not able to set the Subscriber's status to Active unless I use the Update action.

But I don't know what state the subscriber is in -- non existent, or exists-but-unsubscribed -- therefore I don't know whether to do a create or an add. I call your attention to the SaveOptions. Isn't that supposed to give me essentially an Upsert ability? I have this feeling that I'm specifying the SaveOption incorrectly below. Any clues?

  let soapClient = new FuelSoap( fuelOptions );
  let options = {
    "SaveOptions": [{
      "SaveAction":   "UpdateAdd",
      "PropertyName": "*"
    }]
  };

  let props = {
    "EmailAddress":   [email address],
    "SubscriberKey":  [subscriber key],
    "Attributes":     [],
    "Lists":  [ {
      'ID':              [listID],
      'Status':          'Active',
      'StatusSpecified': true,
      'IDSpecified':     true,
      'Action':          'Create'
    }]
  };

  const ERR_SUBONLIST     =  "12014";
  const ERR_ONLISTALREADY =  "13006";

  soapClient.create( 'Subscriber', props, options, function( err ) {
    if (err) {
      if ( _.first( err.results ).ErrorCode === ERR_SUBONLIST ) {
        props.Lists[0].Action = 'Update';
        soapClient.update( 'Subscriber', props, options, function( e ) {
          if (!e) {
            // success
          } else {
            if ( _.first( e.results ).ErrorCode === ERR_ONLISTALREADY ) {
              // you are already on the list
            } else {
              // failure
            }
          }
        });
      } else {
        // failure
      }
    } else {
      // success
    }
  });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.