cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
naulacambra
Frequent Visitor

Create work item at Azure DevOps from an email with attachments

My goal here is to crete work items whenever an email arrives.

 

I've successfully created a flow to create a Work Item at my Azure DevOps board when an email arrives.

 

The issue comes when I try to attach the email attachments to the created Work Item.

 

Since there isn't any "direct" way to do it with an action, I've tried something like this solution where it proposes use the Azure DevOps API service to attach the attachment.

 

According to Azure DevOps Api Documentation (here), to attach a file, I should send the binary data as a json, and I've been trying to achieve that with this flow

Capture.PNG

 Capture2.PNG

{
    "type": "object",
    "properties": {
        "Id": {
            "type": "string"
        },
        "Name": {
            "type": "string"
        },
        "ContentBytes": {
            "type": "string"
        },
        "ContentType": {
            "type": "string"
        },
        "Size": {
            "type": "integer"
        }
    }
}

 

 

Capture3.PNG

binary(body('Parse_JSON')?['ContentBytes'])

 

But it doesn't work. Anyone managed to successfully do this? Any hint would be helpful.

 

Thank you

 

14 REPLIES 14
tfhegdbn
Helper IV
Helper IV

Hi ,

 

Maybe we can turn to @Pieter_Veenstra, and there was a section on "send an http request to sharepoint" in his blog. I think if he has time, he might be able to update the blog about "send an http request to Azure DevOps". That will help us a lot.Smiley Happy

Pieter_Veenstra
Community Champion
Community Champion

Hi @naulacambra,

 

I don't have the Azure Devops setup  to test this out, but lookling at the documentation link that was included in the previous post:

 

https://docs.microsoft.com/en-us/rest/api/vsts/wit/attachments/create?view=vsts-rest-4.1#upload_a_bi...

 

I would say that you need to format the body correctly So it should look somethign like the below JSON. As a test you probably could copy exactly that jason into the body and see if the HTTP request works. Once that works then replace the binary data in the JSON array with your data.

 

{
  "0": 137,
  "1": 80,
  "2": 78,
  "3": 71,
  "4": 13,
  "5": 10,
  "6": 26,
  "7": 10,
  "8": 0,
  "9": 0,
  "10": 0,
  "11": 13,
  "12": 73,
  "13": 72,
  "14": 68,
  "15": 82,
  "16": 0,
  "17": 0,
  "18": 0,
  "19": 24,
  "20": 0,
  "21": 0,
  "22": 0,
  "23": 24,
  "24": 8,
  "25": 2,
  "26": 0,
  "27": 0,
  "28": 0,
  "29": 111,
  "30": 21,
  "31": 170,
  "32": 175,
  "33": 0,
  "34": 0,
  "35": 0,
  "36": 1,
  "37": 115,
  "38": 82,
  "39": 71,
  "40": 66,
  "41": 0,
  "42": 174,
  "43": 206,
  "44": 28,
  "45": 233,
  "46": 0,
  "47": 0,
  "48": 0,
  "49": 4,
  "50": 103,
  "51": 65,
  "52": 77,
  "53": 65,
  "54": 0,
  "55": 0,
  "56": 177,
  "57": 143,
  "58": 11,
  "59": 252,
  "60": 97,
  "61": 5,
  "62": 0,
  "63": 0,
  "64": 0,
  "65": 9,
  "66": 112,
  "67": 72,
  "68": 89,
  "69": 115,
  "70": 0,
  "71": 0,
  "72": 14,
  "73": 195,
  "74": 0,
  "75": 0,
  "76": 14,
  "77": 195,
  "78": 1,
  "79": 199,
  "80": 111,
  "81": 168,
  "82": 100,
  "83": 0,
  "84": 0,
  "85": 0,
  "86": 101,
  "87": 73,
  "88": 68,
  "89": 65,
  "90": 84,
  "91": 56,
  "92": 79,
  "93": 237,
  "94": 204,
  "95": 65,
  "96": 10,
  "97": 192,
  "98": 32,
  "99": 12,
  "100": 68,
  "101": 81,
  "102": 239,
  "103": 127,
  "104": 105,
  "105": 27,
  "106": 240,
  "107": 167,
  "108": 24,
  "109": 146,
  "110": 52,
  "111": 22,
  "112": 138,
  "113": 80,
  "114": 240,
  "115": 237,
  "116": 156,
  "117": 140,
  "118": 211,
  "119": 250,
  "120": 71,
  "121": 206,
  "122": 80,
  "123": 109,
  "124": 227,
  "125": 80,
  "126": 83,
  "127": 188,
  "128": 19,
  "129": 213,
  "130": 217,
  "131": 34,
  "132": 141,
  "133": 164,
  "134": 55,
  "135": 190,
  "136": 70,
  "137": 104,
  "138": 88,
  "139": 73,
  "140": 90,
  "141": 161,
  "142": 55,
  "143": 137,
  "144": 162,
  "145": 53,
  "146": 180,
  "147": 213,
  "148": 198,
  "149": 33,
  "150": 210,
  "151": 60,
  "152": 31,
  "153": 130,
  "154": 33,
  "155": 65,
  "156": 87,
  "157": 249,
  "158": 68,
  "159": 140,
  "160": 230,
  "161": 109,
  "162": 105,
  "163": 200,
  "164": 163,
  "165": 55,
  "166": 249,
  "167": 203,
  "168": 144,
  "169": 224,
  "170": 71,
  "171": 132,
  "172": 134,
  "173": 149,
  "174": 14,
  "175": 9,
  "176": 254,
  "177": 89,
  "178": 220,
  "179": 156,
  "180": 167,
  "181": 161,
  "182": 87,
  "183": 206,
  "184": 80,
  "185": 165,
  "186": 247,
  "187": 11,
  "188": 116,
  "189": 99,
  "190": 71,
  "191": 0,
  "192": 204,
  "193": 122,
  "194": 63,
  "195": 206,
  "196": 0,
  "197": 0,
  "198": 0,
  "199": 0,
  "200": 73,
  "201": 69,
  "202": 78,
  "203": 68,
  "204": 174,
  "205": 66,
  "206": 96,
  "207": 130,
  "208": 0,
  "209": 0,
  "BYTES_PER_ELEMENT": 1,
  "buffer": {
    "0": 137,
    "1": 80,
    "2": 78,
    "3": 71,
    "4": 13,
    "5": 10,
    "6": 26,
    "7": 10,
    "8": 0,
    "9": 0,
    "10": 0,
    "11": 13,
    "12": 73,
    "13": 72,
    "14": 68,
    "15": 82,
    "16": 0,
    "17": 0,
    "18": 0,
    "19": 24,
    "20": 0,
    "21": 0,
    "22": 0,
    "23": 24,
    "24": 8,
    "25": 2,
    "26": 0,
    "27": 0,
    "28": 0,
    "29": 111,
    "30": 21,
    "31": 170,
    "32": 175,
    "33": 0,
    "34": 0,
    "35": 0,
    "36": 1,
    "37": 115,
    "38": 82,
    "39": 71,
    "40": 66,
    "41": 0,
    "42": 174,
    "43": 206,
    "44": 28,
    "45": 233,
    "46": 0,
    "47": 0,
    "48": 0,
    "49": 4,
    "50": 103,
    "51": 65,
    "52": 77,
    "53": 65,
    "54": 0,
    "55": 0,
    "56": 177,
    "57": 143,
    "58": 11,
    "59": 252,
    "60": 97,
    "61": 5,
    "62": 0,
    "63": 0,
    "64": 0,
    "65": 9,
    "66": 112,
    "67": 72,
    "68": 89,
    "69": 115,
    "70": 0,
    "71": 0,
    "72": 14,
    "73": 195,
    "74": 0,
    "75": 0,
    "76": 14,
    "77": 195,
    "78": 1,
    "79": 199,
    "80": 111,
    "81": 168,
    "82": 100,
    "83": 0,
    "84": 0,
    "85": 0,
    "86": 101,
    "87": 73,
    "88": 68,
    "89": 65,
    "90": 84,
    "91": 56,
    "92": 79,
    "93": 237,
    "94": 204,
    "95": 65,
    "96": 10,
    "97": 192,
    "98": 32,
    "99": 12,
    "100": 68,
    "101": 81,
    "102": 239,
    "103": 127,
    "104": 105,
    "105": 27,
    "106": 240,
    "107": 167,
    "108": 24,
    "109": 146,
    "110": 52,
    "111": 22,
    "112": 138,
    "113": 80,
    "114": 240,
    "115": 237,
    "116": 156,
    "117": 140,
    "118": 211,
    "119": 250,
    "120": 71,
    "121": 206,
    "122": 80,
    "123": 109,
    "124": 227,
    "125": 80,
    "126": 83,
    "127": 188,
    "128": 19,
    "129": 213,
    "130": 217,
    "131": 34,
    "132": 141,
    "133": 164,
    "134": 55,
    "135": 190,
    "136": 70,
    "137": 104,
    "138": 88,
    "139": 73,
    "140": 90,
    "141": 161,
    "142": 55,
    "143": 137,
    "144": 162,
    "145": 53,
    "146": 180,
    "147": 213,
    "148": 198,
    "149": 33,
    "150": 210,
    "151": 60,
    "152": 31,
    "153": 130,
    "154": 33,
    "155": 65,
    "156": 87,
    "157": 249,
    "158": 68,
    "159": 140,
    "160": 230,
    "161": 109,
    "162": 105,
    "163": 200,
    "164": 163,
    "165": 55,
    "166": 249,
    "167": 203,
    "168": 144,
    "169": 224,
    "170": 71,
    "171": 132,
    "172": 134,
    "173": 149,
    "174": 14,
    "175": 9,
    "176": 254,
    "177": 89,
    "178": 220,
    "179": 156,
    "180": 167,
    "181": 161,
    "182": 87,
    "183": 206,
    "184": 80,
    "185": 165,
    "186": 247,
    "187": 11,
    "188": 116,
    "189": 99,
    "190": 71,
    "191": 0,
    "192": 204,
    "193": 122,
    "194": 63,
    "195": 206,
    "196": 0,
    "197": 0,
    "198": 0,
    "199": 0,
    "200": 73,
    "201": 69,
    "202": 78,
    "203": 68,
    "204": 174,
    "205": 66,
    "206": 96,
    "207": 130,
    "208": 0,
    "209": 0,
    "byteLength": 210
  },
  "length": 210,
  "byteOffset": 0,
  "byteLength": 210
}

After some more tests, I've sucessfully sent the example json to AzureDevOps as attachments, but now, I have to transform the base64 image that I have at the email object into an array of bytes, such as the example from the documentation. Any tip?

Hi @naulacambra,  I am trying to do the same... do you mind sharing the image of the flow you used to process the attachments?

Hi @maricel0422 at the end I wasn't able to do it "properly". Even though, let me explain my workaround as it could work for you.

 

The mails had two types of attachments, the "in-body" attachments (images inside the email body) and the "attached" attachments. Both of them were described in an array ("attachments") at the end of email object.

 

First, about the first type of attachments;

When an email is received and the flow is triggered, the object received replaced the in-body "src" attribute of the images by something like "src=cid:XXXXXXXXXX@YYYYYYYY". I'm not sure if this is something exclusive of my email client (Outlook.com) or happens all the time. My solution here was to loop through the attachments array, looking for the "id" attribute in the body, and replace the "src" attribute by the base64 representation of the Content-Bytes.

 

About the second type;

My solution was to upload the attachment to OneDrive and then, append the share link into the body content (which later will be the Work Item description). Is not fancy, but it works.

 

Here you will find a link to the json template of my flow. It has a lot more functionalities, but I'm sure you'll be able to extract the part that you're interested in.

 

I hope this helps you

hammer
New Member

I was able to do this using an Azure logic app and an Azure function, instead of flow.  Not sure of your familiarity but from a design/implementation perspective the two (logic app, flow) are similar.  I think my solution would work in flow, I just didn't add a custom connector which I think you need to do in order to call an Azure function from Flow.

 

So, using azure logic app:

 

  • Trigger:  When a new email arrives
    • Check for subject filter to exist
  • Action:  HTML to text (strip out html from email)
  • Action: Create a work item (DevOps)
  • Action:  HttpTrigger (Azure Function)
    • Pass in attachments from email
    • Azure function parses the body (attachments), and creates/attaches for each attachment (inline supported also) - basically just does 2 web requests (for each attachment passed in):
      • POST to create the attachment
      • PATCH to add the attachment to the specific work item
  • Action: Send user email with DevOps ticket # (id)

 

If anyone would like me to elaborate further or has any questions please let me know.  Tested and works.  

Hi @hammer,

would you mind to elaborate the Azure Function part? Even better if you could share your code directly.

 

thanks a lot!

Yes, a more specific example of what you did (codez plz, LOL).

I am new to TFS and DevOps and we are replacing existing Mantis functionality here.

Attachements are a big part (we get screenshots of issues)...

hammer
New Member

So, here is what I did on a more granular level, this also now uses MS Flow and not a logic application:

 

  1. Create Azure Function to handle uploading/associating an attachment to a DevOps workitem
    1. This will also need a DevOps API token
  2. Create an Azure API that will let you access the Azure Function via web request
  3. Send Attachment data in MS Flow using http request action to the Azure API

 

Microsoft Flow:

  • URI = URL created in Azure API that will hit the azure function
  • SubscriptionKey = Key for subscription in Azure API
  • Body:
    • Attachments - this comes from email trigger (not in pic)
    • Subject - this comes from email trigger
    • WorkItemId - this comes from 'create work item 2' step so the function knows which work item to work with

 

Azure Function Code:

#r "Newtonsoft.Json"

using System.Net;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];
    string workItemId = req.Query["workItemId"];

    string tokenFromDevops = @"{TOKEN}";
    string urlDevopsOrgAddAttach = @"https://dev.azure.com/{ORGNAME}/_apis/wit/attachments?api-version=5.0&fileName=";

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    
    name = name ?? data?.name;
    workItemId = workItemId ?? data?.workItemId;

    foreach (var a in data.attachments)
    {
        string attachmentBytes = a.ContentBytes;
        string attachmentFileName = a.Name;
        var bytesFromB = Convert.FromBase64String(attachmentBytes);
        string url = urlDevopsOrgAddAttach + attachmentFileName;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.KeepAlive = false;
        request.Method = "POST";
        request.Headers.Add("Authorization", "Basic " + tokenFromDevops);
        request.ContentType = "application/octet-stream";
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(bytesFromB, 0, bytesFromB.Length);
        requestStream.Close();

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        var rspUploadAttachment = new StreamReader(response.GetResponseStream()).ReadToEnd();
        dynamic jsonResponse = JsonConvert.DeserializeObject(rspUploadAttachment);
        String urlUploadedAttachment = jsonResponse.url;

        // now we need to associate the uploaded attachment to an actual work item
        string urlWorkItem = @"https://dev.azure.com/{ORGNAME}/{PROJECTNAME}/_apis/wit/workitems/" + workItemId + "?api-version=5.0";  
        
        HttpWebRequest requestAttach = (HttpWebRequest)WebRequest.Create(urlWorkItem);
        requestAttach.Method = "PATCH";
        requestAttach.Accept = "application/json";
        requestAttach.Headers.Add("Authorization", "Basic " + tokenFromDevops);
        requestAttach.ContentType = "application/json-patch+json";
        
        string jsonPatchAttach = @"[
  {
    'op': 'add',
    'path': '/fields/System.History',
    'value': 'Adding files from Azure automation'
  },
  {
    'op': 'add',
    'path': '/relations/-',
    'value': {
      'rel': 'AttachedFile',
      'url': 'urlReplaceToken',
      'attributes': {
        'comment': 'Attachment added from Azure automation'
      }
    }
  }
]";
        // this can just be done in json above, but left as-is
        jsonPatchAttach = jsonPatchAttach.Replace("urlReplaceToken", urlUploadedAttachment);
        using (var streamWriter = new StreamWriter(requestAttach.GetRequestStream()))
            {                
                streamWriter.Write(jsonPatchAttach);
                streamWriter.Flush();
           }

        HttpWebResponse responseAttach = (HttpWebResponse)requestAttach.GetResponse();
        var rspAddAttachment = new StreamReader(responseAttach.GetResponseStream()).ReadToEnd();
        // do whatever you want here with response - or nothing
        // dynamic jsonResponse = JsonConvert.DeserializeObject(rspAddAttachment);
    }

    return name != null
        ? (ActionResult)new OkObjectResult($"WorkItemID Created!")
        : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}

 

 

Thanks @hammer you saved me a ton of time getting up and running with a bug tracking implementation using Power Automate Flow and an Azure Function similar to the one you shared. 

 

Also FYI to anyone who also ran into the issue with the DevOps "Send an HTTP request to Azure DevOps" not handling image uploads properly I think I may have found out why. See github @obvioussean's comment here:

https://github.com/MicrosoftDocs/vsts-rest-api-specs/issues/211#issuecomment-503719409

 

Apparently the DevOps Flow connector for "Send an HTTP request to Azure DevOps" is not sending the binary content as true binary but rather as a string. This explains why the image that gets "uploaded" is corrupted. 

 

If anyone else was referring to the DevOps API for attachments when implementing this you were probably also deceived by the request body portion showing a String type. According to github user @obvioussean in the same issue he mentions that the documentation system created this incorrectly.  

@naulacambra Do you know how to load json files to power automate to create a flow? 

Sounds like your solution you shared via json file is the flow I need. 

Hi @ka05th30ry ,

 

just have exactly your described problem with DevOps. 

Have an successfull flow with "Send an HTTP request to Azure DevOps" and cannot open my images. 

See also my issue: https://powerusers.microsoft.com/t5/Using-Flows/Send-an-HTTP-request-to-Azure-DevOps-Successfull-but...

 

So I guess you know the solution how to send the binary content correctly?

Just using the "HTTP" connector instead of the DevOps one? If so, how to create the binary content?

 

Have already tried it with the "HTTP" connector with following body:

 

base64ToBinary(items('Apply_to_each')?['contentBytes'])
 
...but same issue.
 
Would be great if you could help me.
 
Thank you!
 
Cheers,
Sven
Beichler77
New Member

There are some hurdles with the coding to solve. I've found a video which explained it very well: (24) Power Automate - Create Azure DevOps WorkItem and Attachments - YouTube

nehaparakh
Regular Visitor

@Beichler77 i followed the video but still i am getting the following error in the last step of patching have attached the screenshot please help me to identify the issue 

nehaparakh_0-1694788030613.png

 

Helpful resources

Announcements

Celebrating the May Super User of the Month: Laurens Martens

  @LaurensM  is an exceptional contributor to the Power Platform Community. Super Users like Laurens inspire others through their example, encouragement, and active participation. We are excited to celebrated Laurens as our Super User of the Month for May 2024.   Consistent Engagement:  He consistently engages with the community by answering forum questions, sharing insights, and providing solutions. Laurens dedication helps other users find answers and overcome challenges.   Community Expertise: As a Super User, Laurens plays a crucial role in maintaining a knowledge sharing environment. Always ensuring a positive experience for everyone.   Leadership: He shares valuable insights on community growth, engagement, and future trends. Their contributions help shape the Power Platform Community.   Congratulations, Laurens Martens, for your outstanding work! Keep inspiring others and making a difference in the community!   Keep up the fantastic work!        

Check out the Copilot Studio Cookbook today!

We are excited to announce our new Copilot Cookbook Gallery in the Copilot Studio Community. We can't wait for you to share your expertise and your experience!    Join us for an amazing opportunity where you'll be one of the first to contribute to the Copilot Cookbook—your ultimate guide to mastering Microsoft Copilot. Whether you're seeking inspiration or grappling with a challenge while crafting apps, you probably already know that Copilot Cookbook is your reliable assistant, offering a wealth of tips and tricks at your fingertips--and we want you to add your expertise. What can you "cook" up?   Click this link to get started: https://aka.ms/CS_Copilot_Cookbook_Gallery   Don't miss out on this exclusive opportunity to be one of the first in the Community to share your app creation journey with Copilot. We'll be announcing a Cookbook Challenge very soon and want to make sure you one of the first "cooks" in the kitchen.   Don't miss your moment--start submitting in the Copilot Cookbook Gallery today!     Thank you,  Engagement Team

Announcing Power Apps Copilot Cookbook Gallery

We are excited to share that the all-new Copilot Cookbook Gallery for Power Apps is now available in the Power Apps Community, full of tips and tricks on how to best use Microsoft Copilot as you develop and create in Power Apps. The new Copilot Cookbook is your go-to resource when you need inspiration--or when you're stuck--and aren't sure how to best partner with Copilot while creating apps.   Whether you're looking for the best prompts or just want to know about responsible AI use, visit Copilot Cookbook for regular updates you can rely on--while also serving up some of your greatest tips and tricks for the Community. Check Out the new Copilot Cookbook for Power Apps today: Copilot Cookbook - Power Platform Community.  We can't wait to see what you "cook" up!    

Welcome to the Power Automate Community

You are now a part of a fast-growing vibrant group of peers and industry experts who are here to network, share knowledge, and even have a little fun.   Now that you are a member, you can enjoy the following resources:   Welcome to the Community   News & Announcements: The is your place to get all the latest news around community events and announcements. This is where we share with the community what is going on and how to participate.  Be sure to subscribe to this board and not miss an announcement.   Get Help with Power Automate Forums: If you're looking for support with any part of Power Automate, our forums are the place to go. From General Power Automate forums to Using Connectors, Building Flows and Using Flows.  You will find thousands of technical professionals, and Super Users with years of experience who are ready and eager to answer your questions. You now have the ability to post, reply and give "kudos" on the Power Automate community forums. Make sure you conduct a quick search before creating a new post because your question may have already been asked and answered. Galleries: The galleries are full of content and can assist you with information on creating a flow in our Webinars and Video Gallery, and the ability to share the flows you have created in the Power Automate Cookbook.  Stay connected with the Community Connections & How-To Videos from the Microsoft Community Team. Check out the awesome content being shared there today.   Power Automate Community Blog: Over the years, more than 700 Power Automate Community Blog articles have been written and published by our thriving community. Our community members have learned some excellent tips and have keen insights on the future of process automation. In the Power Automate Community Blog, you can read the latest Power Automate-related posts from our community blog authors around the world. Let us know if you'd like to become an author and contribute your own writing — everything Power Automate-related is welcome.   Community Support: Check out and learn more about Using the Community for tips & tricks. Let us know in the Community Feedback  board if you have any questions or comments about your community experience. Again, we are so excited to welcome you to the Microsoft Power Automate community family. Whether you are brand new to the world of process automation or you are a seasoned Power Automate veteran - our goal is to shape the community to be your 'go to' for support, networking, education, inspiration and encouragement as we enjoy this adventure together.     Power Automate Community Team

Hear what's next for the Power Up Program

Hear from Principal Program Manager, Dimpi Gandhi, to discover the latest enhancements to the Microsoft #PowerUpProgram, including a new accelerated video-based curriculum crafted with the expertise of Microsoft MVPs, Rory Neary and Charlie Phipps-Bennett. If you’d like to hear what’s coming next, click the link below to sign up today! https://aka.ms/PowerUp  

Tuesday Tip | How to Report Spam in Our Community

It's time for another TUESDAY TIPS, your weekly connection with the most insightful tips and tricks that empower both newcomers and veterans in the Power Platform Community! Every Tuesday, we bring you a curated selection of the finest advice, distilled from the resources and tools in the Community. Whether you’re a seasoned member or just getting started, Tuesday Tips are the perfect compass guiding you across the dynamic landscape of the Power Platform Community.   As our community family expands each week, we revisit our essential tools, tips, and tricks to ensure you’re well-versed in the community’s pulse. Keep an eye on the News & Announcements for your weekly Tuesday Tips—you never know what you may learn!   Today's Tip: How to Report Spam in Our Community We strive to maintain a professional and helpful community, and part of that effort involves keeping our platform free of spam. If you encounter a post that you believe is spam, please follow these steps to report it: Locate the Post: Find the post in question within the community.Kebab Menu: Click on the "Kebab" menu | 3 Dots, on the top right of the post.Report Inappropriate Content: Select "Report Inappropriate Content" from the menu.Submit Report: Fill out any necessary details on the form and submit your report.   Our community team will review the report and take appropriate action to ensure our community remains a valuable resource for everyone.   Thank you for helping us keep the community clean and useful!

Users online (3,414)